0

I am writing a program in C++. One part of it is this:

std::wcout << "\nEnter path to seed file: ";
char Seed_File_Path[255];//Array for the user to enter a file path
std::cin >> Seed_File_Path;

FILE *seed_file_ifp;                        //Creates pointer to FCB for the seed file.
seed_file_ifp = fopen(Seed_File_Path, "r"); //opens the file input stream with read permissions.

while (seed_file_ifp == NULL) {//Checks that file was found.
    std::wcout << "\nFile not found. Enter a valid path and make sure file exists.\n\n";
    std::wcout << "\nEnter path to seed file: ";
    std::cin >> Seed_File_Path;
    seed_file_ifp = fopen(Seed_File_Path, "r");
}//Ends if ifp successful

I can enter a path less than the size of the array, and the program works as expected. My question is, why does fopen read my path correctly? I would expect it to read in every character in the array, but it reads only what I enter and not past that.

Another characteristic I noticed was that I can enter a large sequence of characters that aren't a valid path (for example, rrrrrr...), then, after the program lets me input a path again, I can enter a smaller sequence of characters that does lead to a valid path (for example, "C:\file.txt") and fopen is able to use the valid path "correctly". However, I would expect it to use as a string all the characters in the array, which include the valid path plus other, previously entered stuff.

I would like to know the characteristic(s) of an array that cause it to work "correctly," and whether that's a good thing or bad.

Peter Cordes
  • 328,167
  • 45
  • 605
  • 847
Josh Peters
  • 151
  • 5
  • 3
    fopen() uses c-string which by definition is a list characters ending to \0 or `NULL`. it does not use array length – Afshin May 31 '18 at 04:42
  • https://stackoverflow.com/questions/4418708/whats-the-rationale-for-null-terminated-strings – Retired Ninja May 31 '18 at 04:44
  • 3
    Just wondering, why are you mixing C and C++ I/O? C++ has classes that handle file I/O more simply. There's also `std::string` so you don't have to torture yourself with char arrays. – eesiraed May 31 '18 at 04:49
  • 4
    @FeiXiang Because I am very young and ignorant and although I have a good mind for CS I haven't filled it with info yet :) – Josh Peters May 31 '18 at 17:33
  • It makes no sense to have expections without being informed. Why do you? (Rhetorical.) If you want to know why your program acts as does, you need to know how fopen & cin & every other function you call act. So read a manual or introduction that tells you. Please also read & act on [ask]. And the downvote arrow mouseover text: "This question does not show any research effort; ...". – philipxy Jun 03 '18 at 06:59
  • @Afshin: `NULL` is a pointer constant. If it's defined as `(void*)0`, it won't convert to a `char` without a cast. Perhaps you meant ASCII NUL (one `L`)? It's clearest to say "zero terminated", because `char` is an integer type and `'\0' == 0`. – Peter Cordes Jun 03 '18 at 17:08
  • @PeterCordes yea, I meant that.but sadly wrote incorrectly. – Afshin Jun 04 '18 at 06:15

2 Answers2

6

When you "enter" your string with cin it automatically adds a '\0' at the n+1 element of the string (n being the size of your string). String operated functions like cout or fopen will only read up to that point. To test this theory you can enter a string 10 characters long, say, and then manually change the 11'th character to something else. Then manually add a '\0' at say the 20th character and print out the string. You'll get a 20 char string with the chars from 10 to 20 being any gibberish.

solarflare
  • 423
  • 3
  • 14
  • 1
    For future readers, when you say "manually", you mean with code like `Seed_File_Path[10] = 'x'; Seed_File_Path[19] = 0;`. Or using a debugger to alter memory while stopped at a breakpoint or while single-stepping. Debuggers are great; printing a `char[]` or `char*` with most debuggers will interpret it as a C string, or you can dump the raw memory and see past the terminating `'\0'` byte. – Peter Cordes Jun 03 '18 at 17:03
2

fopen() uses c-string which by definition is a list characters ending to \0 or NULL. It does not use array length.

When you read path using cin, it automatically adds a \0 character at end of data. So when you try to open it with fopen() you only read it till there and ignore any other character after that \0.

Afshin
  • 8,839
  • 1
  • 18
  • 53