-1

I'm currently practicing File I/O in C. I created a program where I get a file and extract data from it and I would like an option to change the file that is being read. The problem that I'm encountering is that for example I have two files: sample1.txt and sample2.txt. If I chose sample1.txt as the first file to be read and then I wanted to change the file to sample2.txt what ends up happening is that the filename does not change to sample2.txt but instead always stays what ever filename the first file has.

Here is my code:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>
#include <assert.h>
#include <time.h>
#include <ctype.h>
int main()
{
 char file_location[100]={0};
 char new_location[100]={0};
  FILE* fPointer=NULL;
  int choice;

  printf("Enter the filename that you wish to open.\n");
  scanf("%[^\n]s",file_location);               // I enter sample1.txt//
  printf("%s\n",file_location);
  fPointer=fopen(file_location,"r"); // success,sample1.txt is currently being read.//

if (fPointer==NULL)
        {
            printf("File error!,invalid file name! program will now exit.\n");
            exit(0);
        }
else
        {
            printf("Success!\n");       
        }
    printf("Do you want to change the file being read\n); //Now I want to change the file,from sample1.txt to sample2.txt//
    prinft("Enter 1 to change, 0 to exit the program\n); 
    do{
      scanf("%d",&choice);                     
      printf("You entered %d\n",choice);
      if(choice<0||choice>1)
        {
         printf("Error,please choose between 1 and 0\n");
         }

  }while(choice!=1||choice!=0);
      switch(choice)                   // I enter 1,go to case1//
    {
        case 0:
        printf("Exiting program now\n");
        exit(0);
        break;
        case 1:
        fclose(fPointer);
        printf("Enter the filename that you wish to open.\n");    
        scanf("%[^\n]s",new_location);          //scanf does not even prompt me to enter a string.//
        printf("%s\n",new_location);     //nothing prints//
        fPointer=fopen(new_location,"r"); // fpointer still points to sample1.txt//
        break;
    }   

return 0;           
}   

Could anyone explain to me why my code keeps failing? Any constructive criticism ,notes about File I/O is appreciated.

1 Answers1

2

The fundamental problem is that your code mishandles newlines. This method of obtaining input probably does not do what you think it does:

scanf("%[^\n]s",new_location);

First, there is no reason for the trailing s here. Second, this will leave a trailing newline behind in the input stream. This newline is ignored when you call scanf("%d",&choice);, since the %d conversion specifier skips over leading whitespace characters. But, this second call to scanf() also leaves a newline character behind, and this is not ignored by the final call to scanf(), since %[^\n] tells scanf() to read characters until a newline is encountered.

One fix is to simply remove the scanset from your scanf() statements:

scanf("%s", new_location); 

This will ignore leading whitespace characters, so the newline left behind from the previous call to scanf() will be ignored.

Also, when you open the new file, you are using file_location instead of new_location.

You will need to change your do loop condition to:

while(choice != 1 && choice != 0);

since you want to repeat the loop only if the user enters a number that is both not 0 and not 1.

If you want to read lines that include spaces, which is what [^\n] is sometimes used for, a better alternative is to use fgets(). This function keeps the newline, so you will need to remove it from the filenames. Also, if you are using fgets() to get the strings, it is best to use fgets() to get the numeric input, by reading the user input into a buffer and using sscanf() to parse it. Then your input code would look like:

/* Get first filename, and remove the newline */
printf("Enter the filename that you wish to open.\n");
fgets(file_location, sizeof file_location, stdin);
file_location[strcspn(file_location, "\r\n")] = '\0';  // remove newline

...

/* Get numeric input; this keeps the newline, so it does not interfere
 * with the next call to `fgets()` */
char buffer[100];
fgets(buffer, sizeof buffer, stdin);
sscanf(buffer, "%d", &choice);

...

/* Get the new filename, and remove the newline */
printf("Enter the filename that you wish to open.\n");
fgets(new_location, sizeof new_location, stdin);
new_location[strcspn(new_location, "\r\n")] = '\0';  // remove newline
ad absurdum
  • 19,498
  • 5
  • 37
  • 60
  • Thank you ! I will try your suggestion! – Noobplox23 May 14 '17 at 12:07
  • Your suggestion worked! Thank you! I just started learning C this semester and File I/O was the last topic so I wanted to practice File I/O before my finals. – Noobplox23 May 14 '17 at 12:17
  • @Noobplox23-- I have added some comments about using `fgets()` for this, which is a better solution. This allows the entry of strings containing spaces, which is the usual use for the `[^\n]` specifier, but is easier to work with, and more flexible. If you want to read about removing trailing newlines from strings, [this is a good link](http://stackoverflow.com/questions/2693776/removing-trailing-newline-character-from-fgets-input). – ad absurdum May 14 '17 at 12:20