I'm trying to write a set of parameters of a structure into a file, and then read it in the program. The structure has a int type variable and a string type variable(this string is separated by space). I've successfully written and then read the integer part of the structure, but when i try to do the same for the string, the program crashes. I think it has something to do with my the fprintf statement, and trying to read a string separated by space.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <locale.h>
int main(void) {
// creating a FILE variable
FILE *fptr;
// integer variable
int i = 0;
char n[50];
// character variable
struct cliente {
char nome[50];
int nif;
};
struct cliente client[0];
// open the file in write mode
fptr = fopen("student", "w");
if (fptr != NULL) {
printf("File created successfully!\n");
}
else {
printf("Failed to create the file.\n");
// exit status for OS that an error occured
return -1;
}
// get student detail
printf("Enter student name: ");
scanf(" %[^\t\n]c", client[1].nome);
printf("Enter student ID: ");
scanf("%d", &client[1].nif);
// write data in file
fprintf(fptr, "%d %s", client[1].nif, &client[1].nome);
// close connection
fclose(fptr);
// open file for reading
fptr = fopen("student", "r");
// display detail
printf("\Ficheiro:\n");
fscanf(fptr, "%d %s", &i, n);
printf("ID: %d\n", i);
printf(" %s", n);
// close connection
fclose(fptr);
return 0;
}
You are declaring an array of zero length (struct cliente client[0]) but referencing the second element in the array (client[1]). That could cause a crash.
Related
These are 2 separate applications.
In the first one, I tried to store employee details like name, age and salary in the binary file named emp.bin.
In the second application, I tried to view the contents of the file but in place of the name, only the first character appears.
I tried printing each character separately, and it turns out that there's 3 null characters '\n' after each letter in the name that is why it is not printing after the first character.
"Write" application code:
//Receives records from keyboard and writes them to a file in binary mode
#include <stdio.h>
int main()
{
FILE *fp;
char another = 'Y';
struct emp
{
char name[40];
int age;
float bs;
};
struct emp e;
fp = fopen("emp.bin", "wb");
if (fp == NULL)
{
puts("Cannot open the file.");
return 1;
}
while(another == 'Y')
{
printf("Enter the employee name, age and salary: ");
scanf("%S %d %f", e.name, &e.age, &e.bs);
while(getchar() != '\n');
fwrite(&e, sizeof(e), 1, fp);
printf("Add another record? (Y/N)");
another = getchar();
}
fclose(fp);
return 0;
}
"Read" application code:
//Read records from binary file and displays them on VDU
#include <stdio.h>
#include <ctype.h>
int main()
{
FILE *fp;
struct emp
{
char name[40];
int age;
float bs;
} e;
fp = fopen("emp.bin", "rb");
if (fp == NULL)
{
puts("Cannot open the file.");
return 1;
}
while (fread(&e, sizeof(e), 1, fp) == 1)
{
printf("\n%s \t %d \t $%.2f\n", e.name, e.age, e.bs);
}
fclose(fp);
}
Here's the input and output:
How can I correct this code to make it print the whole name?
The problem is in the "writer" application, even before the actual write is performed.
When you get data from the user
scanf("%S %d %f", e.name, &e.age, &e.bs);
you use format %S (capital letter "S". Format specifiers are case sensitive!). As we can read in the printf man page
S
(Not in C99, but in SUSv2.) Synonym for ls. Don't use.
this leads us to %ls format specifier that is described in the following way
s
[...] If an l modifier is present: The const wchar_t * argument is expected to be a pointer to an array of wide characters. Wide characters from the array are converted to multibyte characters
Talking about Windows source we have:
S
Opposite-size character string, up to first white-space character (space, tab or newline). [...]
When used with scanf functions, signifies wide-character array; when used with wscanf functions, signifies single-byte-character array [...]
So, basically, you are reading characters from stdin and converting them to wide chars. In this case every character takes sizeof(wchar_t). Probably in your system this size is 4.
What you need is simply %s format specifier. And since your name array has size 40, I suggest using
scanf("%39s", e.name );
to get the name from user. In this way up to 39 characters will be written, being the 40th reserved to the string terminator '\0'.
As noted by Roberto in his answer, the problem is the %S conversion specifier, which is a typo, you should use %s.
Note however that there are other issues which might pose problems:
you should tell scanf() the maximum number of characters to read for the employee name, otherwise scanf() may write beyond the end of the destination array if input is too long.
if both programs run on separate systems with different endianness, the numbers will be incorrect on the receiving end because their bytes will be stored in the opposite order. For this reason, endianness should be specified and handled explicitly in binary files. Text format tends to be preferred for data transmission.
Here is a modified version:
//Receives records from keyboard and writes them to a file in binary mode
#include <stdio.h>
int main() {
FILE *fp;
char another = 'Y';
struct emp {
char name[40];
int age;
float bs;
} e;
int c;
fp = fopen("emp.bin", "wb");
if (fp == NULL) {
puts("Cannot open the file.");
return 1;
}
while (another == 'Y') {
printf("Enter the employee name, age and salary: ");
if (scanf("%39s %d %f", e.name, &e.age, &e.bs) != 3)
break;
while ((c = getchar()) != EOF && c != '\n')
continue;
if (fwrite(&e, sizeof(e), 1, fp) != 1)
break;
printf("Add another record? (Y/N)");
another = getchar();
}
fclose(fp);
return 0;
}
"Read" application code:
//Read records from binary file and displays them on VDU
#include <stdio.h>
#include <ctype.h>
int main() {
FILE *fp;
struct emp {
char name[40];
int age;
float bs;
} e;
fp = fopen("emp.bin", "rb");
if (fp == NULL) {
puts("Cannot open the file.");
return 1;
}
while (fread(&e, sizeof(e), 1, fp) == 1) {
printf("\n%s \t %d \t $%.2f\n", e.name, e.age, e.bs);
}
fclose(fp);
return 0;
}
I am a complete beginner of C. My problem is to modify a content in a file.
I am writing two files and then merge the contents of the two files in a another file. This another file is the one I need to modify.
what to modify?
The myfile1.txt values are 199112345671273 and the myfile2.txt values are 24AUS2024MED712.
The merging file (myfile3.txt) has 19911234567127324AUS2024MED712
The thing that I need to modify is the values of myfile2.txt. I want to hide its values in asterisk so when reading myfile3.txt,I get the following
199112345671273****************
my logic is messed up. I just want to stores both values of myfile1 and myfile2. then display myfile3 in condition that myfile2 has to be hidden in asterisk when reading.
My write.c program - write data in two files
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_SIZE 100
int main (int argc, char **argv) {
char registration[MAX_SIZE], location[MAX_SIZE], faculty[MAX_SIZE];
int birthOfYear, birthOfMonth, birthOfDate, layerArch1, layerArch2, levelOfStudy, graduatingYear;
FILE *fptr, *anotherfptr;
fptr = fopen("myfile01.txt","w");
anotherfptr = fopen("myfile02.txt", "w");
if(fptr == NULL) {
printf("Error!");
exit(1);
}
printf("Enter a registration number (XXXXXX): ");
scanf("%s", registration); //read as a string
printf("Enter location (location as in currency, AUS CND SIN: ");
scanf("%s", location); //read as a string
printf("Enter faculty (ENG BUS SCI MED): ");
scanf("%s", faculty); //read as a string
printf("Enter birth of year (19XX 200X): ");
scanf("%d", &birthOfYear);
printf("Enter birth of month (XX): ");
scanf("%d", &birthOfMonth);
printf("Enter birth of date (XX): ");
scanf("%d", &birthOfDate);
printf("Enter level of study (1 -first, 2- second, 3- third, 4-fourth, 5 - other): ");
scanf("%d", &levelOfStudy);
printf("Enter graduating year (XXXX): ");
scanf("%d",&graduatingYear);
printf("Enter layer of Architecture 1 (0-sensing, 1-network, 2-smart(hidden), 3-devices): ");
scanf("%d",&layerArch1);
printf("Enter layer of Architecture 2 (0-sensing, 1-network, 2-smart(hidden), 3-devices): ");
scanf("%d",&layerArch2);
fprintf(fptr,"%d%s%d%d%d", birthOfYear, registration, birthOfMonth, birthOfDate, layerArch1); //writing into file with some formatting
fclose(fptr);
fprintf(anotherfptr,"%d%d%s%d%s%d%d", layerArch2, levelOfStudy, location, graduatingYear, faculty, birthOfDate, birthOfMonth);
//writing into file with some formatting
fclose(anotherfptr);
return 0;
}
my merge.c program - to merge two files
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char **argv)
{
FILE *fs1, *fs2, *ft;
char ch, file1[200], file2[200], file3[200];
printf("Enter name of first file\n");
gets(file1);
printf("Enter name of second file\n");
gets(file2);
printf("Enter name of file which will store contents of the two files\n");
gets(file3);
fs1 = fopen(file1, "r");
fs2 = fopen(file2, "r");
if(fs1 == NULL || fs2 == NULL)
{
perror("Error ");
printf("Press any key to exit...\n");
exit(EXIT_FAILURE);
}
ft = fopen(file3, "w"); // Opening in write mode
if(ft == NULL)
{
perror("Error ");
printf("Press any key to exit...\n");
exit(EXIT_FAILURE);
}
while((ch = fgetc(fs1)) != EOF)
fputc(ch,ft);
while((ch = fgetc(fs2)) != EOF)
fputc(ch,ft);
printf("The two files were merged into %s file successfully.\n", file3);
fclose(fs1);
fclose(fs2);
fclose(ft);
return 0;
}
my read.c - to read files
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char **argv) {
char c[1000];
FILE *fptr, anotherfptr;
if ((fptr = fopen("myfile1.txt", "r")) == NULL) {
printf("Error! opening file");
exit(1);
}
// reads text until newline
fscanf(fptr,"%[^\n]", c);
printf("Data from the file:\n%s", c);
fclose(fptr);
if ((fptr = fopen("myfile2.txt", "r")) == NULL) {
printf("Error! opening file");
exit(1);
}
// reads text until newline
fscanf(anotherfptr,"%[^\n]", c);
printf("Data from the file:\n%s", c);
fclose(anotherfptr);
return 0;
}
My issue is my logic on how to solve this simple program. I am literally stuck.
Any help/clarification would be much appreciated.
In this case you need to create a program which should know the content/size of 'myfile1.txt' or 'myfile2.txt' so as to show * for the second content while reading 'myfile3.txt'.
I prefer not to create separate c programs for each task but to use it as a function in one single program.
Coming to the logic : Masking is what you are searching for. Basically it is used as a password masking. ( You might have seen * while typing password in any sites. ). In your case you want to display a content as * without actually changing the content in file.
Get an idea of how masking is done for password in the below document :
https://www.geeksforgeeks.org/print-in-place-of-characters-for-reading-passwords-in-c/
Hope you have tried all possible way out. Please check the solution below :
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char **argv) {
char c1[1000];
char c3[1000];
FILE *fptr, *anotherfptr;
if ((fptr = fopen("myfile1.txt", "r")) == NULL) {
printf("Error! opening file");
exit(1);
}
// reads text until newline
fscanf(fptr,"%[^\n]", c1);
printf("Data from the file myfile1.txt :%s\n", c1);
fclose(fptr);
//calculate the length of string c1
int lengthc1=strlen(c1);
printf("Length of string c1 is : %d\n", lengthc1);
if ((anotherfptr = fopen("myfile3.txt", "r")) == NULL) {
printf("Error! opening file");
exit(1);
}
// reads text until newline
fscanf(anotherfptr,"%[^\n]", c3);
printf("Data from the file myfile3.txt :%s\n", c3);
fclose(anotherfptr);
//to show data of myfile2.txt in astrisk
int lengthc3=strlen(c3);
printf("Final data is ");
for ( int i=0 ; i<=lengthc3 ; i++)
{
if (i < lengthc1)
{
printf("%c", c3[i]);
}
else
{
printf("*");
}
}
return 0;
}
My purpose is to create programme to manage records in files using c. the programme should be able to get info from console, write to a file and then read from it. Struct itself is working fine, but I'm not getting all the values i have written(see output)
and source code
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct dob
{
int date;
int month;
int year;
};
struct person
{
int id;
char firstName[20];
char lastName[20];
struct dob date;
char email[20];
int phoneNo;
}new;
void readRecordsFromFile();
void readRecordsFromKeyboard();
int main(int argc, const char * argv[]) {
puts("Hello");
while (1) {
puts("Select option. \n 1. Read records from file. \n 2. Read records from keyboard \n Type any number to exit\n");
int i;
scanf("%d", &i);
switch (i) {
case 1:
readRecordsFromFile();
break;
case 2:
readRecordsFromKeyboard();
break;
default:
return 0;
break;
}
}
return 0;
}
void readRecordsFromFile(){
//struct person new;
char filename[100];
puts("Scpecify the file name to read data");
scanf("%s", filename);
struct person *new=malloc(sizeof(struct person));
FILE * file= fopen(filename, "rb");
if (file != NULL) {
fread(new, sizeof(struct person), 1, file);
fclose(file);
}
printf("\nID: %d\nName: %s\nSurname: %s\nDay of birth:%d\nMonth of birth:%d\nYear of birth:%d\nE-mail: %s\nPhone Number: %d\n",new->id,new->firstName,new->lastName,new->date.date,new->date.month,new->date.year,new->email,new->phoneNo);
}
void readRecordsFromKeyboard(){
struct person *new=malloc(sizeof(struct person));
puts("Enter the info about person");
puts("ID number");
scanf("%d", &new->id);
puts("First Name");
scanf("%19s", new->firstName);
puts("Last name");
scanf("%19s", new->lastName);
puts("Day, month and year of birth.(by numbers, every is new line)");
scanf("%d", &new->date.date);
scanf("%d", &new->date.month);
scanf("%d", &new->date.year);
puts("Email");
scanf("%19s", new->email);
puts("Phone number");
scanf("%d", &new->phoneNo);
puts("Specify the file you want to write yor data");
char filename[100];
scanf("%99s",filename);
FILE *inputf;
inputf = fopen(filename,"wb");
if (inputf == NULL){
printf("Can not open the file.\n");
exit(0);
}else{
if (fwrite(new, sizeof(new), 1, inputf) != 1)
{
fprintf(stderr, "Failed to write to %s\n", filename);
return;
}else{
puts("Data saved\n");
printf("\nID: %d\nName: %s\nSurname: %s\nDay of birth:%d\nMonth of birth:%d\nYear of birth:%d\nE-mail: %s\nPhone Number: %d\n",new->id,new->firstName,new->lastName,new->date.date,new->date.month,new->date.year,new->email,new->phoneNo);
}
}
fclose(inputf);
}
here is your problem
inputf = fopen(filename,"wb");
This command clears file, because it file is opened with "wb".
If you are going to write multiple record in that file in several runs, open it with "wb+". Then use fseek() to go to end of file. after that write your record with fwrite().
In addition for fwrite() you need to use sizeof strusture, not pointer.Means that you need something like this:
if (fwrite(new, sizeof(struct person), 1, inputf) != 1)
{
}
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main()
{
struct info
{
char name[15];
char surname[15];
char gender[15];
char education[15];
} sem;
FILE *fp=NULL;
int i, a;
char tmp[256] = {0x0};
while(1)
{
printf("Enter the value\n");
scanf("%d", &a);
if((fp = fopen("info.txt", "r")) != NULL)
{
switch(a)
{
case 0:
exit(0);
case 1:
for(i=0;!feof(fp);i++)
{
fscanf(fp, "%s %s %s %s", sem.name, sem.surname, sem.gender, sem.education);
printf("%s, %s, %s, %s\n",sem.name,sem.surname,sem.gender,sem.education);
}
break;
case 2:
while (fgets(tmp, sizeof(tmp), fp) != NULL)
{
if (strstr(tmp, "bachelors"))
{
/* Code works fine until this part */
fprintf(fp, "\n%s %s %s %s", sem.name, sem.surname, sem.gender, sem.education);
}
}
break;
default: printf("Default statement");
}
fclose(fp);
}
}
}
If anyone could point me out what im doing wrong, id be very greatful, I added a comment where code runs in to a problem and doesnt display anything. Basicly i have txt file. Program if user so desires needs to find lines in the file where "bachelor" is typed and give me back all of those lines.
You are opening your file in read mode (fp = fopen("info.txt", "r")) and trying to write in it using fprintf() which is not possible.
Use fp = fopen("info.txt", "r+") i.e read and write mode.
If you want to compare strings, you will have to use strcmp(), not an undefined function like "strstr". Also, strcmp returns 0 if two strings have same value. So you also have to check that the return value of strcmp() is zero or not.
Also as I replied to your question yesterday, fprintf() method appends the characters that you've passed as arguments to file. So, in your code, when you find string "bachelor", you just add same line at the end of the file. If you want to see those data in console, you can use printf() method.
I am working on a program to write user input to a file and then search for a specific record in the file and output it to the screen.
I tried using fgets and also fputs but havent been successful
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
main ()
{
FILE *fileptr;
char id [30];
char name [47];
char amt[50];
int i;
fileptr=fopen("C:\\Users\\Andrea\\Documents\\Tester.txt","w");
if (fileptr == NULL) {
printf("File couldn't be opened\n\a\a");
fclose(fileptr);
exit(0);
}
printf("Enter name: \n");
fscanf(fileptr,"%c",name);
fputs(name,fileptr);
fclose(fileptr);
printf("File write was successful\n");
return 0;
}
There are several problems.
You are trying to read from fileptr.
You are reading only one character, but treat the name array as if it was read in correctly.
A start would be:
[...]
printf("Enter name: \n");
if (fgets(name, sizeof name, stdin)) {
fputs(name,fileptr);
fclose(fileptr);
printf("File write was successful\n");
} else {
printf("Read error.\n");
}
But that's not all: you have forgotten to put error checking. E.g., how do you know that your "File write was successful\n" if you don't check at least the return value of fputs()?