0

I'm trying to have the program check, that, if a user inputs nothing the print statement will say it cant find the file name, but the issue I'm having is that the command line will just go to a new line after hitting enter instead of saying the print statement. This is the code here. I was told that Null is the place holder for if nothing is put in so I thought it would work.

int main()
{
FILE *fin;
FILE *fout;
char fInName[50];
char fOutName[50];
printf("pleas type input file, and output file please type legibly\n ");

scanf("%s %s", &fInName, &fOutName);
fin = fopen(fInName, "r");
fout = fopen(fOutName, "r");

if (fInName == NULL && fOutName == NULL)
{
    printf("Error: Cannot open input file %s.", fInName);
}
else if (fInName != NULL && fOutName == NULL)
 {
    printf("file found");
 }
}

What im trying to test is if a first file name is entered and the second isnt then print the statement. If both arent entered then print file does not exist. there is more to the code to see if the file exists or not, but thst would be a bit much, now Im just trying to understand why it wont read unentered data. Ive tried looking at examples such as: How to detect empty string from fgets and tried to alter the code to fit that type of style but it didnt work for me so Im giving you the code it was originally so that anything helpful wouldnt confuse me more.

Edit: okay so I tried to do a simple code in order to see what may be the cause of this issue:

   int main()
{
    char firstname[50];
    char lastname[50];
    char nothing [0];


    printf("pleas type input file, and output file please type legibly pwease\n ");
    scanf("%s" "%s", firstname, lastname);


 if (firstname == lastname )
{
    printf("Error: Cannot open input file %s.", firstname);
}
else
{
    printf("file found");
}

}

I ran the code using adam and either if I typed adam (space) adam or adam(enter) adam the program thinks that the input is not the same, I feel like that would help identify why it doesnt know why nothing is typed in.

Community
  • 1
  • 1
  • 1
    it should be if (fInName == NULL || fOutName == NULL) in first and if (fInName != NULL && fOutName != NULL) in the second part probably – Pooya Apr 17 '16 at 00:56
  • If both names are valid, nothing will be printed. Perhaps this is what's happening already? As it stands there are 4 possible states - #0 both invalid, #1 both valid, #2 first one valid, #3 second one valid. You're only checking for two of the possible states: #0 and #2. You may also consider checking the filename before trying to open a file - if the name's no good, no reason to do any more with it. :) – enhzflep Apr 17 '16 at 00:58
  • 2
    You should be checking the return value of `scanf`. If it fails to get your two strings, the values of `fInName` and `fOutName` will be whatever random thing happened to be in them before you made the call. The behavior at that point could be a number of things since you're essentially trying to open two files with random names, which may or may not exist. – Tibrogargan Apr 17 '16 at 01:02
  • What do you think these checks do? Do you think they check if the string is empty? Or do you think they check if the file is open? If you want a check for an empty filename, why isn't the check code *before* the call to `fopen`? – David Schwartz Apr 17 '16 at 01:05
  • 1
    Neither `fInName` nor `fOutName` will ever be NULL; they're both array names and array names are never equal to the null pointer. (Note: arguments to a function are pointers, not truly arrays — pointers can be null, of course.) You should check the return value from `scanf()`; if it says 2, you got two file names; otherwise, you have problems of some sort. Note that if you get two names, neither will be an empty string. You should check the file names before trying to open the files, too. Note that you should preface your pleas for good behaviour with 'Please'. – Jonathan Leffler Apr 17 '16 at 01:05
  • Also, why are you checking the *names* and then saying the file was found? Shouldn't you be checking the files? – David Schwartz Apr 17 '16 at 01:05
  • For ease of understanding and readability by us humans: 1) indent the code consistently. indent after every opening brace '{'. unindent before every closing brace '}'. Suggest each indent level by 4 spaces as that is wide enough to be visible even with variable width fonts. 2) separate code blocks (for, if, else, while, do...while, switch, case, default) via a blank line. – user3629249 Apr 17 '16 at 01:09
  • when calling any of the `scanf()` family of functions, always check the returned value (not the parameter value) to assure the operation was successful. – user3629249 Apr 17 '16 at 01:10
  • when calling the function: `fopen()`, always check (!=NULL) the returned value to assure the operation was successful. – user3629249 Apr 17 '16 at 01:10
  • 1
    regarding this text: `please type legibly` The user will be typing at some kind of keyboard. How could it possibly not be legible? – user3629249 Apr 17 '16 at 01:14
  • the posted code contains a `if, else if` sequence. in general that is nonsense. Suggest:, immediately after the each call to `fopen()` something like: `if( NULL == fin ) { perror( "fopen for input file failed" ); exit( EXIT_FAILURE ); }` and `if( NULL == fout ) { perror( fopen for output file failed"); fclose( fin ); exit( EXIT_FAILURE );` naturally, call `fclose()` for each of the file pointers before exiting the program. – user3629249 Apr 17 '16 at 01:20
  • when calling `scanf()` with a format specifier of '%s' always include a max characters modifier (that is one less than the length of the input buffer, in this case use 49) Suggest: `if( 2 != scanf( "%49s %49s", &fInname, &fOutName ) ) { // suggest using `fprintf( stderr, ... )` then `exit( EXIT_FAILURE ); }` – user3629249 Apr 17 '16 at 01:25
  • the posted code contains some 'magic' numbers. (I.E. 50) 'magic' numbers make the code much more difficult to understand, debug, maintain. Suggest using a `#define` statement to give the magic numbers a meaningful name, then using that meaningful name throughout the code. – user3629249 Apr 17 '16 at 01:27
  • the check if the user did not enter any text for the file names, use the `strlen()` function. If the returned value is 0 then nothing was entered – user3629249 Apr 17 '16 at 01:30
  • @user3629249 the legibly thing was a joke, I do that for me to have a bit of fun – Adam Spencer Baker Apr 17 '16 at 01:32
  • @user3629249 the magic number, from what I read and watch many times, is the number of space held for the name of the input like "Adam" would take up 4 spaces. – Adam Spencer Baker Apr 17 '16 at 01:37
  • There is nothing 'magic' about the strlen of the string: `Adam`. That was not what is being discussed by 'magic' numbers in the code. 'magic' numbers are when the code contains some number with no justification and no real meaning. the numbers 0 and 1 are normally not considered to be 'magic' numbers. Almost all other numbers in the code are considered to be 'magic' numbers. – user3629249 Apr 17 '16 at 06:14
  • I do appreciate useful things in code, such as 355.0/113.0 = 3.14159292 is a usable approximation of PI for many applications. Meaningless statements are not appreciated. It reminds me of back in the days of 80 column card decks and some time and resource waster used the comment area of the cards in an assembly language program to write a story about some bunny rabbit. Creative, but totally unappreciated by the programming staff and the management. – user3629249 Apr 17 '16 at 06:24
  • 1
    actually some input like: `Adam` would take up 5 bytes/spaces due to the trailing NUL ('\0') character. – user3629249 Apr 17 '16 at 06:26

1 Answers1

0

The problem is occurring when you try to check if fInName == NULL.

The problem is that fInName is just a variable that you're using to store the name of the file that you want to open. What you actually want to check is that the user gave you a valid filename, and to do so you will want to understand what the return value of functions are.

For example, when you try to open a file using fopen(), if fopen() is unable to successfully open the file, say because the user didn't input anything or misspelled the filename, then fopen() will return NULL, storing it in whatever variable you assigned it to (in your case, *fin and *fout).

Also, scanf() is not recommended for char arrays because if the user inputs more data than you allocated for the array, which in this case is enough space for 50 characters, then scanf() will try to write data to memory that's not yours, causing a buffer overflow.

A much safer option is to use fgets() because you can choose exactly how much data is written into your char array, with the only downside being that fgets() will write newline characters \n (caused by hitting the enter key) into the array, though the simple solution is to overwrite the newline character with '\0'.

Therefore, I would propose:

int main(void)
{
    char fInName[50];
    char fOutName[50];

    // ensure proper usage
    do
    {
        printf("What file would you like to open? ");
        // get infile from user and remove trailing newline '\n' character
        fgets(fInName, 50, stdin);
        fInName[strcspn(fInName, "\n")] = '\0';
    }
    // prompt for input until user enters something
    while (strlen(fInName) < 1);

    do
    {
        printf("What file would you like to output to? ");
        // get outfile from user and remove trailing newline '\n' character
        fgets(fOutName, 50, stdin);
        fOutName[strcspn(fOutName, "\n")] = '\0';
    }
    // prompt for input until user enters something
    while (strlen(fOutName) < 1);

    FILE *fin = fopen(fInName, "r");

    if (fin == NULL)
    {
        printf("Error: Cannot open input file %s.", fInName);
        return 1;
    }
    else
    {
        printf("file found");
    }
}
Austin
  • 11
  • 3
  • If it is `fout` that is null, the error message is not accurate. You should report errors on stderr, ideally. The messages should end with a newline. And `"file found"` should say which file. You should check the result of `scanf()`. – Jonathan Leffler Apr 17 '16 at 03:21
  • hey I tried it and I have the same issue cant really figure out why – Adam Spencer Baker Apr 17 '16 at 03:41
  • I tried to leave as much of your original code as possible intact and missed something else that would have caused an error. Originally it said "if (fin == NULL || fout == NULL)" but you don't want to check for fout to be NULL because at that point you haven't created fout, so no matter what it's going to be NULL. I've updated my code and it should work now for checking if the infile is valid and was successfully opened. Also, are you planning on using fout to write the contents of fin therein? Because if so, when using fopen on fOutName, you would want the second argument to be "w", not "r" – Austin Apr 17 '16 at 11:36
  • the issue that keeps popping up is that the computer is constantly waiting on the first input, it doesn't know that nothing is being produced it thinks that something is being typed somewhere else. – Adam Spencer Baker Apr 17 '16 at 13:42
  • Adam, I believe that error is being caused by scanf not knowing how to handle an input of \n (when the user **only** hits enter). I've updated my code (and provided further explanation) above. Although the code is a little bit more complex than your original code, it's a much safer program because it uses more error handling. I hope this helps! – Austin Apr 17 '16 at 15:36
  • havent read the code but i want to think you for sticking with me this long really i appreciate it. – Adam Spencer Baker Apr 17 '16 at 15:50
  • Also, I just saw your edit where you're trying to compare `firstname == lastname`. The problem with that is that when comparing char arrays[] (or char *pointers), you can't compare them using the equality operator `==`, because what that does is compare the **address** of each variable, which will always be different. Instead, use the `strcmp()` function like so: `if (strcmp(word1, word2) == 0)` – Austin Apr 17 '16 at 15:54
  • No, it would be the variable names. So using your original edit code for example: `if (strcmp(firstname, lastname) == 0)` – Austin Apr 17 '16 at 16:09