C - Writing char arrays to a file - c

I have the following struct:
struct visitordata {
char name[25];
char email[25];
int id;
char reg_time[9];
};
I want to write data from these visitors into a file. I'm reading this data from the CLI:
int main(int argc, char** argv)
{
struct visitordata mydata;
char name[25], email[25], eventid[10], c;
printf("Enter name: ");
scanf("%s", name);
strcpy(mydata.name, name);
//etc.
}
Now when I try to write to the file:
lseek(handle, -sizeof(mydata.name), SEEK_END);
fputs(handle, &mydata.name);
This writes the input the user gave alright, but also some gibberish, since I allocated char name[25]
How can I allocate the char array sizes after reading from the command line? I'm pretty new to this, please don't be harsh. Thank you!

struct visitordata mydata;
memset(mydata, 0, sizeof mydata);
if (scanf("%24s %24s", mydata.name, mydata.email) == 2) {
...
}
The memset fills mydata with 00 bytes, so that your file doesn't contain random data.
When passing an array to a function, only a pointer to its first element is really passed, and this is exactly what scanf expects. Note that for reading an int, you would have to write:
if (scanf("%d", &mydata.id) == 1) {
...
}

Use strlen(name) to get how many character are in the name.

Related

Creating an array with unknown size of input files

I newer in C language. I could not solve my problem. I have a input file, let's say input.txt. We know there are 4 column on every line. Nevertheless, we do not know how many lines are there. I give you sample input.txt:
Student,James,12,65
Teacher,Jane,23,60
Teacher,Michael,30,75
Student,Erric,15,73
First column can be 2 different things like student or teacher. 2nd column will be unique. No repeated names. 3rd column will be ages of the person's. 4th column will be weights. Also, I am trying to make 2D array. So, my goal is:
arrName = {{Student, James, 12, 65}, {Teacher,Jane,23,60}, {Teacher,Michael,30,75}, {Student, Erric, 15,73}}
I am trying to create like this array. The array must be dynamically. because we do not know how many lines are there. I could not split the every line by commas. I have tried strdot. how can I parse the lines with comma, and add them into 2D array? Also, I got confused about pointers. While creating 2D array, do we have to use like char **arrPtr;? Or using like *arrPtr is enough for creating 2D array?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define COLUMN 4 //We know that there are 4 column in chars.txt file.
int main(int argc, char const *argv[]) {
char *arrName;
int nameLines;
arrName = (char *) malloc( sizeof( char ) );
FILE *FileName;
FileName = fopen(argv[1], "r");
if (FileName == NULL) {
printf("The Name file could not open!\n");
exit(0);
}
else{
char c;
while ( (c == fgetc(FileName)) != EOF ) {
if (c == '\n') {
nameLines++;
}
}
printf("%d\n", nameLines);
}
return 0;
}
I could not continue after else statement. Can you help me?
You got a bunch of errors in your code like this for example.
while ( (c == fgetc(FileName)) != EOF ) { -> Comparison of constant -1 with boolean expression is always true
So let's start fresh. This is how I would read a comma separated file and dynamically allocate memory to an array of ´read´ objects. It's actually less lines of code then you would expect.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define COLUMNS 4
#define MAX_STRING_LENGTH 100 //Enter the maximum characters allowed as profession and name
typedef struct theDAta{
char type[MAX_STRING_LENGTH+1];
char name[MAX_STRING_LENGTH+1];
unsigned int age;
unsigned int weight;
}theData;
int main(int argc, char const *argv[]) {
theData* allDataPtr=malloc(1); //Pointer to all entries
theData currentData; //The current read data
int currentBlock=0; //the index currently 'active'
FILE *fp = fopen(argv[1], "r");
if (!fp) {
printf("The file you provided can't be read!\n");
exit(EXIT_FAILURE);
}
while (fscanf(fp, "%[^,],%[^,],%d,%d\n", currentData.type, currentData.name,&currentData.age,&currentData.weight) == COLUMNS) {
allDataPtr=realloc(allDataPtr, sizeof(theData)*(currentBlock+1));
if (!allDataPtr) {exit(EXIT_FAILURE);} //Memory allocation failure. Ok so here i lost my pointer to the previous memory.. However we let the OS garbage collect us.
memcpy(allDataPtr+currentBlock++, &currentData, sizeof(currentData));
}
for (int x=0; x<currentBlock; x++) {
printf("Profession: %s\nName: %s\nAge: %d\nWeight: %d\n\n",allDataPtr[x].type,allDataPtr[x].name,allDataPtr[x].age,allDataPtr[x].weight);
}
fclose(fp);
free(allDataPtr);
return 0;
}
So what I do is to create a struct containing the stuff I want to populate from the file. Then I populate that object and extend the memory with the size of that object and then copy the read data to the end of that memory block.. That's basically it... Hope you get great grades :) !!
/Anders
EDIT
Was a bit bored this evening, so let's shave the code... And humm, well. This is not part of my official answer :-) but you could bling it like this (it's actually also skipping one layer of memory copy :) and the engine is 3 lines of C code if you define a line of C code delimiter as ';'->
typedef struct j{
char t[MAX_STRING_LENGTH+1];
char n[MAX_STRING_LENGTH+1];
unsigned int a;
unsigned int w;
}j;
int main(int argc, char const *argv[]) {
j* g;
int l=0;
FILE *h;
if((!(h=fopen(argv[1],"r"))||(!(g=malloc(sizeof(j))))))exit(-1);
while(fscanf(h,"%[^,],%[^,],%d,%d\n",g[l].t,g[l].n,&g[l].a,&g[l].w)==COLUMNS)if(!(g=realloc(g,sizeof(j)*(++l+1))))exit(-1);
for(int x=0;x<l;x++)printf("Profession: %s\nName: %s\nAge: %d\nWeight: %d\n\n",g[x].t,g[x].n,g[x].a,g[x].w);
fclose(h);
free(g);
return 0;
}

Error while trying to read from file C

I have a file and i need to read data from it. I have to read 2 int and 1 c string.
This is my struct
typedef struct seats
{
int number, reserved;
char * name;
} seats;
This is my main
FILE *data;
seats input;
data = fopen("data.txt", "r+");
while(fscanf(data,"%s %d %d", input.name, &input.number, &input.reserved) != EOF)
{
printf("%s %d %d", input.name, input.number, input.reserved);
}
Every time when i compile and run this software it crashes for some reason. Is there any solution?
You haven't assigned any value to input.name, but you pass its garbage value to fscanf. You need to assign a variable a value before you attempt to use that value.
Change your struct to something like this:
typedef struct seats{
int number, reserved;
char name[1000];
} seats;
and put a fflush(stdin), after printf(...)

fscanf only scans in the first value of my file

#include <stdio.h>
#include <stdlib.h>
struct account{
int accountId;
char *name;
double amount;
};
int main(int argc, char **argv)
{
FILE *file=fopen(argv[1],"r");
struct account *Ptr;
int i,j;
int size=0;
fscanf(file,"%d",&size);
if(size==0)
{
printf("Unable to open file");
return 0;
}
printf("%d",size);
Ptr=malloc(sizeof(struct account)*size);
for(i=0;i<size;i++)
{
fscanf(file,"%d%s%lf\n",&(Ptr+i)->accountId,(Ptr+i)->name,&(Ptr+i)->amount);
}
for(j=0;j<size;j++)
{
printf("%d%s%lf\n",((Ptr+j)->accountId),(Ptr+j)->name,((Ptr+j)->amount));
}
fclose(file);
free(Ptr);
return 0;
}
This is used to read in the input file
2
2 Harry 23.45
8 Sally 100.91
Somehow the code reads in the first 2 for size and the second 2 during the for loop but nothing else
Your code has undefined behavior, because you are reading data into an uninitialized pointer:
fscanf(file,"%d%s%lf\n",&(Ptr+i)->accountId,(Ptr+i)->name,&(Ptr+i)->amount);
// ^^^^
// This pointer is uninitialized ----------------------+
There are three ways to address this:
Make name an array, rather than a pointer, e.g. char name[MAX_NAME], or
Use malloc to allocate space to name before reading data into it.
Read into a temporary buffer, then malloc the exact number of chars.

reading 7 variables (1 line per variable) from a file and assigning to struct variables

I'm making a simple enrollment system that maintains a database of a collection of computer science students. Each student record contains
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct student
{
char name[300];
int age;
char course_1[40];
char course_2[40];
char *remarks;
};
struct course
{
char course_title[200];
int cse_num[100];
char instructor[200];
char date[50];
char start_time[50];
char end_time[50];
char location[50];
};
main()
{
int i;
struct course data[11];
FILE *f;
char title[100];
int num[100];
char instructor[100];
char date[100];
char start_time[100];
char end_time[100];
char location[100];
char line[300];
f = fopen("course.dat", "r");
i=0;
while(*fgets(line, 300, f) != '\n')
{
sscanf(line, "%99[^\n]", num);
sscanf(line, "%99[^\n]", title);
sscanf(line, "%99[^\n]", instructor);
sscanf(line, "%99[^\n]", date);
sscanf(line, "%99[^\n]", start_time);
sscanf(line, "%99[^\n]", end_time);
sscanf(line, "%99[^\n]", location);
data[i].cse_num = num // doesn't work
strcpy(data[i].course_title, title);
strcpy(data[i].instructor, instructor);
strcpy(data[i].date, date);
strcpy(data[i].start_time, start_time);
strcpy(data[i].end_time, end_time);
strcpy(data[i].location, location);
i++;
}
fclose(f);
}
My question is how to take in the input from the file since it is 7 lines until a new line is considered. I tried my best to explain this, thanks if you can try to help me guys!! I really focused on this just couldn't figure it out to be honest. This is the file:
Example input:
CSE1001
Research Directions in Computing
Wildes, Richard
W
16:30
17:30
VC 135
Do not forget, you must also strcpy(data[i].course_title, title);
and that goes for all strings.
You are currently doing this: data[i].course_title = title;
Consider the use of scanf. It's a general use function for parsing input from the terminal or from a file with the fscanf variant. It's already a part of the libraries you'd be including, and is similar in formatting to printf which you'll use lots for program output.
You've misdeclared main():
struct course
{
char course_title[200];
int cse_num[100];
char instructor[200];
char date[50];
char start_time[50];
char end_time[50];
char location[50];
}
main()
{
This says that main() returns a struct course. That's wrong.
Add a semi-colon after the structure.
Always provide an explicit type for every function. C99 requires it; it is good practice for C89.
The code should start:
struct course
{
char course_title[200];
int cse_num[100];
char instructor[200];
char date[50];
char start_time[50];
char end_time[50];
char location[50];
};
int main(void)
{
You should be getting warnings from your C compiler about this mistake. If you weren't, you either need to turn warnings on or you need to get a better compiler.
This may or may not be directly related to the other problems you face, but it should be fixed.

printing data from a struct

I have a nested array of structures in the following form:
#include <stdio.h>
#include <stdlib.h>
typedef struct
{
char* e_name;
char* e_lastname;
}emp_name;
typedef struct
{
emp_name name;
int id;
}emp;
int main(int argc, char *argv[])
{
int i;
int cod=100;
emp job[3];
for (i=0;i<3;i++)
{
scanf("%s",&job[i].emp.e_lastname);
job[i].id=cod;
cod++;
}
for (i=0;i<3;i++)
{
printf("%s",job[i].emp.e_lastname);
printf("%d\n",job[i].id);
}
system("PAUSE");
return 0;
}
but the program hangs in the printing part, why is that?
Thanks
You have three problem:
First you want to access:
job[i].name.e_lastname
not
job[i].emp.e_lastname
Second You should have:
scanf("%s",&job[i].name.e_lastname);
instead of
scanf("%s",job[i].name.e_lastname);
You do not pass & since it is an array you are passing to the scanf function.
Third problem you should allocate memory to your char *e_lastname and char *e_name camps of the struct emp_name.
Note that:
scanf
int scanf ( const char * format, ... );
Reads data from stdin and stores them according to the parameter
format into the locations pointed by the additional arguments.
The additional arguments should point to already allocated objects
of the type specified by their corresponding format specifier within
the format string. (source)
So you want this:
int main(int argc, char *argv[])
{
int i;
int string_size = 10;
int cod=100;
emp job[3];
for (i=0;i<3;i++) // Allocate space for the string you will access.
{
job[i].name.e_name = malloc(sizeof(char)*string_size);
job[i].name.e_lastname = malloc(sizeof(char)*string_size);
}
for (i=0;i<3;i++)
{
scanf("%s",job[i].name.e_lastname);
job[i].id=cod;
cod++;
}
for (i=0;i<3;i++)
{
printf("%s",job[i].name.e_lastname);
printf("%d\n",job[i].id);
}
system("PAUSE");
return 0;
}
Consider the fact that using scanf is unsafe, because:
If you use the %s and %[ conversions improperly, then the number of
characters read is limited only by where the next whitespace character
appears. This almost cetainly means that invalid input could make your
program crash, because input too long would overflow whatever buffer
you have provided for it. No matter how long your buffer is, a user
could always supply input that is longer. A well-written program
reports invalid input with a comprehensible error message, not with a
crash. (source)
Nevertheless, their are some workaround that you can do to use scanf (check them here)
Instead of scanf you can use fgets. fgets allows you to limit the data that will be placed in your buffer.
You really need to be careful with pointers and what is allocated or not.
I have rewritten your code but with the wrong solution. check comments.
#include <stdio.h>
#include <stdlib.h>
typedef struct emp_name {
/*
* now there you had just char*. this decares
* a pointer to some memory but no memory is allocated.
* if you were going with that approach you should initialize
* the struct and assign those values to something you malloc'ed().
* This version suffers from fixed size and a possible buffer overflow if
* you chose scanf to write the data in the buffer.
*/
char e_name[512];
char e_lastname[512];
/*
* try to follow conventions. your previous struct declarations
* were anonymous. if it caught an error you wouldn't know in which
* struct it would be. good practices here: link1 (bottom)
*/
} emp_name_t;
typedef struct emp {
emp_name_t emp;
int id;
} emp_t;
int main(int argc, char *argv[]) {
int i;
int cod=100;
emp job[3];
for (i=0;i<3;i++) {
/*
* check out this excelent post for a secure alternative:
* link2 (bottom)
*/
scanf("%s",&job[i].emp.e_lastname);
job[i].id=cod;
cod++;
}
for (i=0;i<3;i++) {
printf("%s",job[i].emp.e_lastname);
printf("%d\n",job[i].id);
}
return 0;
}
link1: openbsd style(9)
link2: disadvantages of scanf
I see you have:
typedef struct
{
char* e_name;
char* e_lastname;
}emp_name;
typedef struct
{
emp_name name;
int id;
}emp;
emp job[3];
So what is .emp doing in the following line? Its not a member of any structure
job[i].emp.e_lastname

Resources