Mister 832
Mister 832

Reputation: 1221

Build file path in c++

I'm new to c++ and want to read a csv file and print out the number of lines.

The directory of the file is passed as commandline argument and the file name is given. The following line should build the path to the csv:

//argv[1] = C:\Users\me\source\repos\sol1\proj1\bin\x64\Debug\191003-070100\
string verpfad = argv[1] + std::string("veraenderungen.csv");

//verpfad shows as: C:\Users\me\source\repos\sol1\proj1\bin\x64\Debug\191003-070100 in the console

Next, i tried to put the backslash in front of the file name and remove it from the commandline argument:

//argv[1] = C:\Users\me\source\repos\sol1\proj1\bin\x64\Debug\191003-070100
string verpfad = argv[1] + std::string("\\veraenderungen.csv");
//verpfad shows as: C:\Users\me\source\repos\sol1\proj1\bin\x64\Debug\191003-070100 in the console

Next i tried

//argv[1] = C:\Users\me\source\repos\sol1\proj1\bin\x64\Debug\191003-070100
string verpfad = argv[1] + '\\' + std::string("veraenderungen.csv");
//verpfad shows as: veraenderungen.csv in the console

How can I fix this?

For completeness the whole code:

#include "pch.h"
#include <iostream>

//meine includes
#include <string>
#include <fstream>

using namespace std;

int main(int argc, char* argv[])
{
    // this line 
    string verpfad = argv[1] + std::string("veraenderungen.csv");


    ifstream ver(verpfad);

    if (!ver.is_open()) std::cout << "Datei " << verpfad << "kann nicht geöffnet werden" << '\n';

    //Anzahl der Zeilen in der Datei
    std::count(std::istreambuf_iterator<char>(ver), std::istreambuf_iterator<char>(), '\n');

    ver.close();

    std::cout << "Pfad ist: ";
    std::cout << argv[1] <<  std::endl;

    system("pause");

    return 0;
}

Upvotes: 1

Views: 126

Answers (1)

yzt
yzt

Reputation: 9113

TL;DR: Do this:

string verpfad = std::string(argv[1]) + '\\' + "veraenderungen.csv";

And that's it.

The problem is (unfortunately) related to pointers and implicit casting and backwards-compatibility with C and operator associativity and some other technicalities in the C++ language.

You see, argv[1] is not a "string" (i.e. std::string) but merely a pointer to a NUL-terminated array of characters. However, applying the + to a char * on the left and a std::string on the right (i.e. argv[1] + std::string("...")) is legal and it does a string concatenation, which is what you want here.

But then you go and put a single character between them (which should be of the type char, but quite often, it is an int) which changes the evaluation of the result of the + operation. Now that you are adding three things together, the first add is done first, which is between a pointer and an integer, and its result is far from string concatenation.

The correct way (well, one correct way) is to make the first thing on that line (argv[1]) into a std::string. The type std::string can concatenate characters and pointer to NUL-terminated arrays of characters and some other things to itself using the + operator, and the result of those operations are all std::strings again, and when there are multiple + operators in the same expression they are evaluated from left-to-right... so you'll be fine!

One more thing to remember: contrary to some other languages, adding numbers to a std::string won't work. You can use the std::to_string(x) to turn numbers into strings.

Upvotes: 1

Related Questions