I'm having issues trying to read a white space character in C. What I want to do is read user input when asking for a first and last name.
So for example, I prompt the user to enter their name, they type in something like "Peter Smith". With that info, I want to write it to a file.
When it writes it to a file, the file only reads the last name "Smith". How can I read the whole string?
Here's how I asked:
printf("\nPlease enter your first and last name: \n");
scanf("%[^\n]", name);
fgets(name, sizeof(name), stdin);
I don't think your problem lies in the snippet you posted. Here's an example program I wrote on my Linux system to try and pinpoint the issue:
#include <stdio.h>
int main()
{
char name[128];
int num_scans = 0;
FILE *out = fopen("name.txt", "w");
if(out == NULL)
{
printf("Failed to open file for write.\n");
return 1;
}
printf("\nPlease enter your first and last name: \n");
num_scans = scanf("%127[^\n]", name);
if(num_scans < 1)
{
printf("Error reading name.\n");
return 2;
}
fprintf(out, "%s\n", name);
fclose(out);
return 0;
}
This appeared to work for me:
$cat name.txt
Peter Smith
If you post the code you used to write the name to a file, that might reveal the source of the error.
The code is working correctly. The fgets call replaces the value you read for the first name.
You should stick to one scheme of input. When you switch between input paradigms "strange" things happen. (Technically they are exactly what is supposed to happen, but typical users tend to not be too precise about exactly how each function works, and what state the input stream is left in.)
Related
So I've written a program that will take in a information about a dvd (specifically it's postion, IDkey(just some random number) Title, Genre and Year of release), and using a struct it will write that info to a .txt file called "person.txt". I'm positive my code works for the most part but when I go to test it the output received in the .txt file is written in some weird symbol language and not English and quite frankly I have no idea as to why this is. Any explanation on why this is happening would be much appreciated, thanks :)
PROGRAM
#include <stdio.h>
#include <stdlib.h>
// a struct to read and write
struct dvd
{
int fposition;
int fIdKey;
char ftitle[50];
char fgenre[50];
int fyear;
};
int main ()
{
FILE *outfile;
struct dvd input;
// open file for writing
outfile = fopen ("person.txt", "w");
if (outfile == NULL)
{
fprintf(stderr, "\nError opend file\n");
exit (1);
}
printf("Postion: ");
scanf("%d", &input.fposition);
printf("ID Key: ");
scanf("%d", &input.fIdKey);
printf("Title: ");
scanf("%s",&input.ftitle);
printf("Genre: ");
scanf("%s", &input.fgenre);
printf("Year: ");
scanf("%d", &input.fyear);
// write struct to file
fwrite (&input, sizeof(struct dvd), 1, outfile);
if(fwrite != 0)
printf("contents to file written successfully !\n");
else
printf("error writing file !\n");
// close file
fclose (outfile);
return 0;
}
TEST RUN
TEST RUN OUTPUT IN THE .TXT FILE
You are writing these values to the file:
int fposition;
int fIdKey;
char ftitle[50];
char fgenre[50];
int fyear;
But you are displaying the whole file as characters. That kind of works for ftitle and fgenre because they really are characters...though since you don't populate all 50 characters there are some ugly uninitialized characters shown as well. That is easy to fix: just fill the unused characters (as well as the null terminator) with some known character (such as space) before writing to the file, or do not write the unused characters at all. You can use strlen() to find the length of each string and memset() to set the unused characters to a well-known character which is printable.
Next, saving an int and reading it as text is problematic. You need to decide on a single format. Either you write as integers like now, and you read as integers (which means you need a special program to read the file), or you commit to writing only text to the file.
Easiest might be to only write text to the file. You can use fprintf() for that, instead of fwrite(). You can use fprintf() for the character arrays as well, it will automatically write only the "used" part of each string up to the null terminator, skipping all the "garbage" characters.
My Program Works Mostly, except for When I try to read the Total Data that was Entered
#include <stdio.h>
#include <string.h>
#define bufferSize 300
char name[50], gift[50], list[300], end[50], *result;
int i;
int main()
{
FILE *appendPlace = fopen("NamesAndGifts.txt", "a");
FILE *readData = fopen("NamesAndGifts.txt", "r"); //my place for reading data
printf("This is a Gift Entering System for 3 People Only\nThe Name of the Person then their Gift Description will be taken\nThe Gift Description is Basically the Gift Name");
while (strcmp(end, "END") != 0) {
printf("\nEnter Name of Person %d or type 'END' to Exit Sequence\n", i + 1);
scanf("%s", &end);
if (strcmp(end, "END") != 0) {
strcpy(name, end);
printf("Now Enter Gift Description (Gift Name) of Person %d\n", i + 1);
scanf("%s", &gift);
strcat(list, "\n");
strcat(list, "Name: ");
strcat(list, name);
strcat(list, "\n");
strcat(list, "Gift: ");
strcat(list, gift);
strcat(list, "\n");
}
i++;
}
printf("The Gift Entering System (Names and their respective Gifts) is Below:\n");
printf("%s", list);
fputs(list, appendPlace);
fclose(appendPlace);
//below I attempt to read file Data to be able to print file's Data into running program
fscanf(readData, "%s", result);
printf("\n\n\n\n\n\n\nTotal Data in File Below:\n%s", result);
fclose(readData);
}
I tried out doing just file reading, and it seems that reading from the file like that can only read data that is not separated by (space bar) or (enter)
Is there a way to Solve this?
So there are 2 problems in your code.
result has no memory allocated to it. Since it is a global variable, it is initialized to 0, aka a NULL pointer. So your scanf() sees that and the reading fails and so does printf() and prints "(null)". The solution there is to allocate memory in result either by making it a static array or by using malloc().
Even if you fix the first problem, however, it will still not work as expected as fscanf() will stop reading input after the first whitespace is encountered. Since you want the whole (file) input to be read, you have four options:
Read character by character (not advisable for performance reasons but perhaps the easiest to implement)
read line by line (fairly a standard way)
read chunk by chunk given some pre-allocated buffer or
read the whole file at once (not advised for big files)
The functions to use are fgetc(), getline(), fread(). Additionally, you can find the size of the file by following this question
I'm trying to make a small program that saves some information on a file, taking input from the user for the content and name of the file. For some reason, I am unable to save file_name into FILE *open.
This works when input a string as the file name; open = fopen("filename.txt","w"); but not when I try to input string as a variable. I have looked all over and cannot find an answer anywhere.
I have included stdio.h and string.h
int main (){
FILE *open;
char first_name[16],last_name[21];
char save_name[30],ext[10];
char file_name[40];
int a,b;
printf("This program will take your name and save it in a file.\n");
printf("Insert your first name:");
scanf("%s",&first_name);
printf("Insert your last name:");
scanf("%s",&last_name);
do{
printf("Insert file name with extension:");
scanf("%[^.].%s", &save_name, &ext);
//Takes filename lenght, minus the dot
a = (int)strlen(save_name)-1;
b = (int)strlen(ext);
sprintf(file_name,"%s.%s",save_name,ext);
}while(a>8 || b>3);
//This is where my problem lies...
open = fopen(file_name,"w");
if(open==NULL){
printf("File %s failed to open, shutting down...",file_name);
}
else{
fprintf(open, "%s %s",first_name,last_name);
printf("\n\nSave successful! File was saved as: %s",file_name);
}
fclose(open);
return 0;
}
The problem is that your file_name has a leading newline character in it! The newline is being added by your scanf() call with the "%[^.]" format (but I'm not entirely sure why). It seems that using %s for string input automatically removes this but %[^.] will accept all characters except . (including whitespace). Use this to fix it (skipping the newline):
scanf("\n%[^.].%s", &save_name, &ext);
Comments welcome as to where this newline comes from - it's news to me!
PS: You don't need the - 1 in your calculation of a, as the dot is never read into save_name.
Program(A)-----> file.txt-----> Program(B)
^This is the format I am using, I currently don't have enough knowledge with file structures.
My text file is named myStudents.txt
EDIT: Program(A) writes the information properly. Program(B) needs to retrieve the information from the text file.
#include<stdio.h>
int main()
{
char studentName[50];
int grade=0;
printf("Which students grade would you like to retrieve?: ");
scanf("%s",&studentName);
FILE *fptr;
fptr = (fopen("myStudents.txt", "r"));
if(fptr == NULL)
{
printf("Error!");
exit(1);
}
printf("\nStudent details:\n");
fscanf(fptr,"%d %[^\n]s",grade,studentName);
printf("Name: %s\n",studentName);
printf("Grade: %d\n",grade);
fclose(fptr);
return 0;
}
I'm very confused on how to use program A's information in program B. Apologies if this is a repeat thread, I couldn't find any information here or anywhere else to solve my issue.
*Note(A solid explanation would be very helpful along with any constructive criticism)
Cheers! Have a good day!
Your program B does actually not search for any name, it just tries to print the first one. I won't write the complete code for you but here is a little help with what your program should do:
read in the file line by line. (functions fscanf, fgets or getline may be useful)
extract the name and grade out of the line. (sscanf and all string functions)
check if the name is the one you are looking for, if yes print it and stop.
This is of course only an example what the program could look like, but i suggest to start by implementing this steps.
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.
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");
}
}