Write to txt file - c

I have a problem when trying to write to a txt file. I'm making a car register and after adding 2 cars to it, it looks like this in the txt file.
BMW
Car
ABCD1234
Herald
45
Fiat
Car
QWER1234
RONALD
20
My wish is to get it on the same line like this.
BMW Car ABCD1234 Herald 45
Fiat Car QWER1234 RONALD 20
This is my "save" and "add vehicle" function atm.
int save(vehicle_t * v, int count)
{
FILE * f;
f = fopen("reg.txt", "w");
if(f == NULL)
{
printf("Could not open!\n");
return 0;
}
else
{
int i;
for(i=0; i < count; i++)
{
fprintf(f, "%s %s %s %s %d\n", v[i].brand, v[i].type, v[i].reg, v[i].owner.name, v[i].owner.age);
}
}
fclose(f);
}
void add_vehicle(vehicle_t *v, int count)
{
char brand[NSIZE]; char type[NSIZE]; char reg[NSIZE]; char name[NSIZE];
int age;
printf("Brand: ");
fgets(brand, NSIZE, stdin);
strcpy(v[count].brand, brand);
printf("Type of vehicle: ");
fgets(type, NSIZE, stdin);
strcpy(v[count].type, type);
printf("Reg number: ");
fgets(reg, NSIZE, stdin);
strcpy(v[count].reg, reg);
printf("Owners name: ");
fgets(name, NSIZE, stdin);
strcpy(v[count].owner.name, name);
printf("Owners age: ");
v[count].owner.age = num_check(MAX_AGE, MIN_AGE);
}
My thought is that fgets adds \n at the end of an array, but how do I get rid of this problem when working with structs?

fgets returns all the characters on the line including the trailing \n. To keep fprintf from printing the \n characters you can change the fprintf call to
fprintf(f, "%*.*s %*.*s %*.*s %*.*s %d\n",
strlen(v[i].brand)-1, strlen(v[i].brand)-1, v[i].brand,
strlen(v[i].type)-1, strlen(v[i].type)-1, v[i].type,
strlen(v[i].reg)-1, strlen(v[i].reg)-1, v[i].reg,
strlen(v[i].owner.name)-1, strlen(v[i].owner.name)-1, v[i].owner.name,
v[i].owner.age);
This instructs it to output all but the last character of each string.

You can put the terminator one position to the left with:
fgets(name, NSIZE, stdin);
name[strlen(name) - 1] = '\0';
or you could use scanf:
scanf("%100[^\n]%*c", name);
//but here I've put a maximum 100 chars inside the string,
//not using the variable
There are other ways to do that with scanf but if you are a beginner I'd recommend you to stick with one of the two options above.

Related

fscanf string from file

I have i file "student_read.txt" that my code is supposed to read from.
the file contains this:
3872187
John Doe
21
then its going to print the information as seen in the print_student function. but it seems like when it reads from the file with fscanf it detects the space between John and doe as enter which makes it so the output is.
student id: 3872187
full name: John
age: Doe
what can i do to make it print the output:
student id: 3872187
full name: john doe
age: 21
#include <stdio.h>
#include <string.h>
#define STRING_LENGTH 100
//Struct with alias student_t that contains student information.
typedef struct student_t{
char studentId[STRING_LENGTH];
char studentName[STRING_LENGTH];
char studentAge[STRING_LENGTH];
}student_t;
//function for printing the student information
void print_student(struct student_t student){
printf("\nStudent id: %s\n", student.studentId);
printf("Name: %s\n", student.studentName);
printf("Age: %s\n", student.studentAge);
}
int main() {
//Use the defined struct to crate an instance of Student
struct student_t student;
//Zero out all the memory of the struct instance
memset(&student, 0, sizeof(student));
//selecting option
int option;
printf("Choose an option");
scanf("%i", &option);
switch(option){
case 1:{
FILE* read = fopen("student_read.txt", "r");
fscanf(read, "%s", &student.studentId);
fscanf(read, "%s", &student.studentName);
fscanf(read, "%s", &student.studentAge);
print_student(student);
}
break;
case 2:{
//Asks for student_t id
printf("\nStudent id: ");
scanf("%s", &student.studentId);
//getchar(); is used to prevent newline in input of fgets function.
getchar();
//Asks for full name (strcpy since datatype = string)
char name[STRING_LENGTH] = {0};
printf("\nFull name: ");
fgets(name, STRING_LENGTH, stdin);
name[strlen(name)- 1] = 0;
strcpy(student.studentName, name);
//Asks for age
printf("\nAge: ");
scanf("%s", &student.studentAge);
}
break;
case 3:{
printf("Program closing");
}
break;
default:
printf("Invalid Option... Try again");
}
/*
FILE* write = fopen("student_write.txt", "w");
if (read==0){
printf("failed to open file\n");
return -1;
}
fclose(read);
fclose(write);
*/
return 0;
}
You can use fgets instead of fscanf. This function will be reading characters until it finds a newline character or end-of-file, so it won't stop at the whitespace.
Edit: if you need to use fscanf compulsory, you can check this response: R: Can fscanf() read whitespace?

scanf("%[^\n]%*c", …) in a loop

I have to program a new file in which I have to have multiple student info (like: Student_name, student_Surname, school_subject and number of student) in one line and I have to type in new students until I input END.
I have to use printf and scanf. Name, surname and subject can be multiple words When I try to use scanf("[^\n]*c", name), I can only enter info for one student and loop just ignores rest and for other students I can just type in student number which is integer.
What is wrong with my code?
int main() {
FILE *outputfile = NULL;
struct imenik {
char prezime[17 + 1];
char ime[13 + 1];
char predmet[20 + 1];
int bodovi;
} ucenik;
outputfile = fopen("imenik.txt", "w");
printf("Ucitaj ime ucenika: ");
scanf("%[^\n]%*c", ucenik.ime);
printf("Ucitaj prezime ucenika: ");
scanf("%[^\n]%*c", ucenik.prezime);
printf("Ucitaj predmet: ");
scanf("%[^\n]%*c", ucenik.predmet);
printf("\nUcitaj broj bodova (0-50): ");
scanf("%d", &ucenik.bodovi);
fprintf(outputfile, "%s | %s | %s | %d\n", ucenik.ime, ucenik.prezime, ucenik.predmet, ucenik.bodovi);
fclose(outputfile);
}
The problem is here:
scanf("%d", &ucenik.bodovi);
This reads the number, but it doesn't read the newline after it. So when the loop repeats, It reads that newline as an empty line of input for the next student name.
You can change it to:
scanf("%d ", &ucenik.bodovi);
The space tells it to skip over any whitespace after the number.
But actually, it's better to put the space at the beginning of each scanf, rather than ignoring the newline at the end. See http://stackoverflow.com/questions/19499060/what-is-difference-between-scanfd-and-scanfd for the explanation. So change it to:
printf("Ucitaj ime ucenika: ");
scanf(" %[^\n]", ucenik.ime);
printf("Ucitaj prezime ucenika: ");
scanf(" %[^\n]", ucenik.prezime);
printf("Ucitaj predmet: ");
scanf(" %[^\n]", ucenik.predmet);
printf("\nUcitaj broj bodova (0-50): ");
scanf("%d", &ucenik.bodovi);
I suggest you an implementation like this:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define S_SIZE 32
#define T_SIZE 128
int main(void) {
FILE *outputfile = NULL;
struct imenik {
char prezime[S_SIZE];
char ime[S_SIZE];
char predmet[S_SIZE];
int bodovi;
} ucenik;
outputfile = fopen("imenik.txt", "a");
if (outputfile == NULL) {
perror("Fopen");
exit(EXIT_FAILURE);
}
char tmp[T_SIZE];
while (1) {
printf("Enter info separated with spaces: ");
fgets(tmp, T_SIZE, stdin);
if (strcmp(tmp, "END\n") == 0) {
break;
}
sscanf(tmp, "%s %s %s %d", ucenik.ime, ucenik.prezime, ucenik.predmet, &ucenik.bodovi);
fprintf(outputfile, "%s | %s | %s | %d\n", ucenik.ime, ucenik.prezime, ucenik.predmet, ucenik.bodovi);
}
fclose(outputfile);
return 0;
}
Your line:
scanf("%d", &ucenik.bodovi);
leaves a newline in the input stream. This gets picked up by the next call to scanf(), which immediately exits, also leaving the newline behind, and so on. Do not try adding a trailing whitespace character to the format string, as some suggest: "%d ". This will consume the newline at the end of your input, and wait for more input, until a non-whitespace character or EOF is encountered.
The easiest solution is to do what you have already been doing to discard newlines:
scanf("%d%*c", &ucenik.bodovi);
Note that you should specify a maximum width in format strings when using scanf() to read into a string to avoid buffer overflow:
scanf("%13[^\n]%*c", ucenik.ime);
Also, you should be checking outputfile to be sure that the file has opened successfully.
One way to implement the loop would be to place the first call to scanf() outside of the loop, then use strcmp() in the while statement to check for "END". At the end of the loop, duplicate the first call to scanf():
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void) {
FILE *inputfile = NULL;
FILE *outputfile = NULL;
struct imenik {
char prezime[17 + 1];
char ime[13 + 1];
char predmet[20 + 1];
int bodovi;
} ucenik;
outputfile = fopen("imenik.txt", "w");
/* Did file open successfully? */
if (outputfile == NULL) {
perror("Unable to open file:");
exit(EXIT_FAILURE);
}
/* Specify maximum widths in calls to scanf() */
printf("Ucitaj ime ucenika: ");
scanf("%13[^\n]%*c", ucenik.ime);
while (strcmp(ucenik.ime, "END") != 0) {
printf("Ucitaj prezime ucenika: ");
scanf("%17[^\n]%*c", ucenik.prezime);
printf("Ucitaj predmet: ");
scanf("%20[^\n]%*c", ucenik.predmet);
printf("\nUcitaj broj bodova (0-50): ");
scanf("%d%*c", &ucenik.bodovi);
fprintf(outputfile, "%s | %s | %s | %d\n",
ucenik.ime, ucenik.prezime, ucenik.predmet, ucenik.bodovi);
printf("Ucitaj ime ucenika: ");
scanf("%13[^\n]%*c", ucenik.ime);
}
fclose(outputfile);
return 0;
}

Program to search a word in file and print the line that it occurs

Write a C program that read a the name of a file and one word from the keyboard. The program must print all lines of the file who has this word.
I can't find a way to make this work.
I did this:
char nome_arq[20];
printf("Tell me the name of file: ");
scanf(" %s", nome_arq);
FILE *fp = fopen(nome_arq, "r");
if(!fp) return 0;
char palavra[40];
printf("Tell me the word: ");
scanf(" %s", palavra);
while(!feof(fp)) {
char palavra2[40];
fscanf(fp, " %[^' ']", palavra2);
if(!strcmp(palavra, palavra2)) {
char linha[400];
fgets(linha, 400, fp);
printf("%s\n", linha);
}
}
return 0;
but it just print the line since the word to the end.
Help please.

Error when trying to store multiple information into text file

i'm trying to write a database to store information of staff. Here is my problematic code:
#include<stdio.h>
int main(){
char name[100], gender[100], email[100], id[10], phone[20];
FILE *fPtr;
fPtr=fopen("staffinfo.txt","w");
FILE *fPtr1;
fPtr1=fopen("staffinfo.txt","a+");
if (fPtr == NULL)
printf("Error in opening file\n");
if (fPtr1 == NULL)
printf("Error in opening file\n");
printf("\n===Add New Staff Profile===");
printf("\n\nPlease enter the following staff information.");
printf("\n\nStaff ID: ");
scanf("%s", &id);
fflush(stdin);
printf("Name\t: ");
fgets(name,100,stdin);
printf("Gender\t: ");
scanf("%s", &gender);
printf("Phone\t: ");
scanf("%s", &phone);
printf("Email\t: ");
scanf("%s", &email);
fprintf(fPtr, "Staff ID\t Name\t\t Gender\t\t Phone\t\t Email");
fprintf(fPtr1, "\n%s\t\t %s\t\t %s\t\t %s\t %s", id, name, gender, phone, email);
printf("\nSYSTEM: New Staff Profile is Added Successfully.");
fclose(fPtr);
fclose(fPtr1);
return 0;
}
The output give:
===Add New Staff Profile===
Please enter the following staff information.
Staff ID: 1
Name : Carmen Gray
Gender : Female
Phone : 123-4567890
Email : carmen#live.com
SYSTEM: New Staff Profile is Added Successfully.
--------------------------------
Process exited with return value 0
Press any key to continue . . .
However, the output in text.file is not as expected:
Staff ID Name Gender Phone Email
1 Carmen Gray
Female 123-4567890 carmen#live.com
The problem lies with this code:
fflush(stdin);
printf("Name\t: ");
fgets(name,100,stdin);
If I use scanf instead of fgets, I cannot store strings with spaces.
Can anyone suggest me how to make it work?
well, you have the whole string, you just need to put a null terminator on the end of the string or pass it to a new string:
int i = 0;
int lastPlace = 0;
for(i=0 ; i < 100 ; i++)
{
if(name[i] == '\n')
name[i] = '\0';
}
as zubergu said:
fgets Reads characters from stream and stores them as a C string into str until
(num-1) characters have been read or either a newline or the end-of-file is
reached, whichever happens first.
A newline character makes fgets stop reading, but it is considered a valid
character by the function and included in the string copied to str.
A terminating null character is automatically appended after the characters
copied to str.
this means the problem in your code is that you write the newline charecter to the file. just remove it!
full code:
#include<stdio.h>
int main(){
char name[100], gender[100], email[100], id[10], phone[20];
FILE *fPtr;
fPtr=fopen("staffinfo.txt","w");
FILE *fPtr1;
fPtr1=fopen("staffinfo.txt","a+");
if (fPtr == NULL)
printf("Error in opening file\n");
if (fPtr1 == NULL)
printf("Error in opening file\n");
printf("\n===Add New Staff Profile===");
printf("\n\nPlease enter the following staff information.");
printf("\n\nStaff ID: ");
scanf("%s", &id);
fflush(stdin);
printf("Name\t: ");
fgets(name,100,stdin);
// MY CODE EXAMPLE HERE
int k = 0;
int lastPlace = 0;
for(k=0 ; k < 100 ; k++)
{
if(name[k] == '\n')
name[k] = '\0';
}
printf("Gender\t: ");
scanf("%s", &gender);
printf("Phone\t: ");
scanf("%s", &phone);
printf("Email\t: ");
scanf("%s", &email);
fprintf(fPtr, "Staff ID\t Name\t\t Gender\t\t Phone\t\t Email");
fprintf(fPtr1, "\n%s\t\t %s\t\t %s\t\t %s\t %s", id, name, gender, phone, email);
printf("\nSYSTEM: New Staff Profile is Added Successfully.");
fclose(fPtr);
fclose(fPtr1);
return 0;
}
The problem is fgets reads '\n' and inputs it in your char array, and then puts '\0' at the end. So you basically include new line character to your string. What you have to do is to remove '\n', because it will be placed in your output file and mess up the results.

User Input to File

I'm creating a program that should create a structure of a list of people entered by the user; the only problem I'm having is getting the user input data to appear in the text file. Anyone know how to do this? Here is the code:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
struct person{
char name[20];
int age;
struct person *next_ptr;
} PERSON;
int main (void){
struct person PERSON;
FILE *fp;
char ans, ch;
int ppl=0;
fp=fopen("person_struct", "w");
if(fp != NULL){
while(ppl<25){
printf("Would you like to add a person to the list? [y/n] ");
scanf("%c", &ans);
if(ans == 'y') {
printf("\nEnter a name:\n");
scanf("%s", PERSON.name);
fprintf(fp, "%s",PERSON.name);
printf("\nEnter age:\n");
scanf("%i", &PERSON.age);
fprintf(fp, " %i\n", PERSON.age);
}
else {
ppl=25;
}
ppl++;
}
fclose(fp);
}
printf("\n\n\n");
system("pause");
return 0;
}
Youe scanf statement is wrong you forgot ampersand & operator before PERSON.age its int
scanf("%i", PERSON.age);
^ & missing
correct is:
scanf("%i", &PERSON.age);
You have two scanf stamens in your code to inputs from user one for string to scan name.
scanf("%s", PERSON.name);
This is correct and No need of & before string. But age is int and to scan int.float you need to add & before variable that is why added ampersand & before PERSON.age.
ref: scanf
Second:
fputs(PERSON.age, fp); is wrong syntax of fputs is:
int fputs( const char *str, FILE *stream );
^ you are passing int
first argument should be const char* but your are passing int
fputs(PERSON.age, fp);
^ wrong , age is int not char*
When you need formatting input/output prefer printf and scanf functions, My suggestion change your read/write like: (read comments)
printf("Enter a name:\n");
scanf("%s", PERSON.name); // here is No & because `name` is string
scanf("%i", &PERSON.age); // age is `int` so & needed
fprintf(fp,"%s %i\n",PERSON.name, PERSON.age);
EDIT: Because you commented, your code is working after these rectifications, see
$ gcc x.c -Wall
$ ./a.out
Would you like to add a person to the list? [y/n]y
Enter a name:
yourname
14
Would you like to add a person to the list? [y/n]y
Enter a name:
firendName
15
Would you like to add a person to the list? [y/n]n
sh: 1: pause: not found
$ cat person_struct.txt
yourname 14
firendName 15
In addition to Grijesh's answer:
Please explain scanf("%s", &ans);. How many characters can you store in ans? How many characters does the string "y" require to store? Verify your beliefs: printf("sizeof ans: %zu\n" "sizeoof \"y\": %zu\n", sizeof ans, sizeof "y");
Perhaps you meant: if (scanf("%c", &ans) != 1) { /* assume stdin has closed or reached EOF */ }. Note the %c, which will read only one character into ans.
Alternatively, if you change ans to an int, you can use: ans = getchar();
edit: In short, I think your loop should look something like this:
for (size_t ppl = 0; ppl < 25; ppl++){
int ans;
printf("Would you like to add a person to the list? [y/n]");
do {
ans = getchar();
while (ans >= 0 && isspace(ans));
if (ans != 'y') {
break;
}
printf("Enter a name:\n");
if (scanf("%s", PERSON.name) != 1 || scanf("%i", &PERSON.age) != 1) {
break;
}
fprintf(fp, "%s %i\n", PERSON.name, PERSON.age);
}

Resources