What I am doing -
I am trying to read a file that contains information about processes and create 3 different arrays. One for array name, second for arrival time and third for process time and compute it afterwards. The number of processes are not fixed but for testing purposes I am keeping it to 4 processes.
The first printf line outputs what I desire. The file contents in the form of array.
void readFile() {
int i = 0;
char printLine[10];
char *processName[4];
char *arrivalTime[4];
char *processTime[4];
FILE *processFile = fopen("processes.txt", "r");
while(!feof(processFile)){
fgets(printLine, 10, processFile); // get the line
processName[i] = strtok(printLine, " ");
arrivalTime[i] = strtok(NULL, " ");
processTime[i] = strtok(NULL, "");
printf("%s %s %s\n", processName[i], arrivalTime[i], processTime[i]);
i++;
}
printf("----\n%s %s %s\n", processName[0], arrivalTime[0], processTime[0]);
}
Error -
The error(sort of) is that the output of 2nd print line gives me the last process information even though I am printing the 1st element(1st process) information. So, instead of printing 1st element it is printing the last.
processes.txt file looks like this
P1 0 3
P2 1 6
P3 4 4
P4 6 2
P.S.
The format of this file will be fixed so no issue there.
I am a real real novice in this. Please excuse my silliness.
EDIT - my output
This is because of the way strtok works, it doesn't return a pointer to a copy of the token, it returns a pointer to the first character of the token in the ORIGINAL location. You need to create a copy yourself.
basically, after the first read you have the following situation:
[ 1^'P','1','\0',2^'0','\0',3^'3','\0']
1: printLine,processName[0]
2: arrivalTime[0]
3: processTime[0]
So printLine and processName[0] are just pointing at the first position -marked by 1^-.
arrivalTime[0] is just pointing at the 4th position -marked by 2^-.
processTime[0] is just pointing at the 6th position -marked by 3^-.
Where basically all you "string"s -which are actually just character pointers- are pointing to different points within the same sequence of characters.
When you read the new string, it overwrite the old data, but the pointers stay where they are.
After your loop is done you have the following situation:
[ 1^'P','4','\0',2^'6','\0',3^'2','\0']
1:printLine,processName[0],processName[1],processName[2],processName[3]
2:arrivalTime[0],arrivalTime[1],arrivalTime[2],arrivalTime[3]
3:processTime[0],processTime[1],processTime[2],processTime[3]
As you can see, everything is just pointing at different places in the same sequence of characters.
Related
So I'm creating a program called convert.c that takes in data from a csv file and writes the data to a new textfile called data.bin (but with alterations to the original csv file). One field/column of the csv file in particular contains a column of integers, which were written to the data.bin file. In my analyzeInjuries.c file, I'm trying to write a program that reads in the data.bin file and calculates the total number of integers within that specific column (representing the total number of injuries caused by hurricanes).
I calculated the total number of injuries in my convert.c file and printed it in the terminal. It worked, however when I try to do the same in the analyzeInjuries file, it prints a value of 0. I'm not sure why this is happening as the getfield function and calculations worked fine in convert.c.
I believe there is something wrong with the line char *two = getfield(buf, 2); because when I attempt to print all values in field two, it causes a segmentation fault. Any help with this would be extremely appreciated. I'm really confused as to what went wrong in the analyzeInjuries.c file.
analyzeInjuries.c:
int numDisast= 0;
while (fgets (buf, lineCount, fd)) {
char *second = getfield (buf, 2); //printing second field causes seg fault
int field = POINTER2INT(second);
numDisast = numDisast + field;
}
printf("%d\n", numDisast);
return 0;
}
The image below is a screenshot of the data.bin file. The red line indicates the field I'm trying to find the sum of.
I assume that by "printing third field causes seg fault" you mean trying to print second variable.
getfield() returns NULL if it doesn't find the field and because it uses , as a separator and your data.bin doesn't use ,, then it will always return NULL. Then when you try to print it, it will crash.
Beside that you are not really summing values in the column. Your POINTER2INT macro does not convert a string to an integer. You probably want to use atoi() instead.
EDIT
First: you should check for NULL in you loop:
char *second = getfield (buf, 3);
if (second) {
printf("found field: %s\n", second);
numDisast = numDisast + atoi(second);
}
else {
printf("field not found\n");
}
Second: your data.bin looks like it might use tabs instead of , as the separator. You could change "," to "\t" in your call to strsep() and see if it helps.
I am doing a school project in C and I am stuck at this puzzle.
So, we need to implement a message passing system using sockets for 100 users.
I am storing my users' data in this struct.
typedef struct user
{
char username[20];
int online; //flag value 1 = online, 0 = offline
msg *message_list;
int message_count;
}
And one service we need to implement is to pull a list of all currently connected users. I have written this function for that task.
void all_connected(char buf[2300])
{
printf("\n entering all_connected for %d iterations",user_count);
int i, count = 1;
char tmp[25];
for (i=0; i<user_count; i++)
{
if(users[i] -> online == 1)
{
sprintf(tmp, "\n\t%d. %s", count++, users[i] -> username);
strcat(buf, tmp);
}
}
printf("\n exiting all_connected");
}
Now for some weird reason, when I call this function when the service is requested, it prints the first printf (entering all_connected for x iterations); but it doesn't print the one that I've put on the last line.
Does this mean that the function is getting stuck on some line? I checked and it is iterating 'user_count' times, but never coming on the last line.
What might be a reason for this happening?
This format string "\n\t%d. %s" (assuming up to 20 characters per user) will need a 26-bytes (ASCII) buffer. Here's why:
1 or 2 bytes for the "\n" (depending on the system)
up to 2 bytes for "%d" (presuming you count up to 99)
2 bytes for ". "
up to 20 bytes for "%s"
Your temporary buffer char tmp[25]; is too narrow - has to be at least 26 bytes big (counting the NULL-terminator).
If you have a list of 100 users that would require a total buffer of at least 2601 bytes but from the looks of it you are only providing the function with the buffer of the size 2300. Side note, just specifying the function's input parameter as being char buf[2300] doesn't do anything to actually allocate that buffer. You'd have to make sure you supply the necessary buffer when you call your function.
The reason you are not getting the second printf() is because your program terminates before reaching that point. The reason for termination is memory access violation - that happens when you try to write something into the memory that doesn't belong to your buffers (either a small one or the bug one)
I want read text file and store in array then show.
This is my code:
int i = 0, line = 5;
char ch[100];
FILE *myfile;
myfile = fopen("test.txt","r");
if (myfile== NULL)
{
printf("can not open file \n");
return 1;
}
while(line--){
fscanf(myfile,"%s",&ch[i]);
i++;
printf("\n%s", &ch[i]);
}
fclose(myfile);
return 0;
}
This is my text:
test 123562
856
59986
But result:
est
2356
56
9986
What is wrong? :(
ch[i] is holding a single character. Statement fscanf(myfile,"%s",&ch[i]); will scan string to ch[i] which can hold only one character. There is no place for '\0' which leads your program to undefined behavior.
Change
fscanf(myfile,"%s",&ch[i]);
to
fscanf(myfile,"%s",ch);
Previous answer was wrong. Behavior of program is well defined but you are scanning the file in a wrong manner. Your program will work as expected if you place i++; after printf statement.
while(line--){
fscanf(myfile,"%s",&ch[i]);
printf("\n%s", &ch[i]);
i++;
}
The reason is that &ch[i] is a pointer to the ith element of the array and string will be stored in array starting at position i. For the input given, this will work because the given array is large enough to hold the string.
You can do this as:
while(line--){
fscanf(myfile,"%s",ch);
printf("\n%s", ch);
i++;
}
but it will overwrite the array ch each time a string is scanned to it. Better to use a two dimensional array to store strings and read file with fgets.
You're not going to be able to fit five lines in the single char ch[100] array; that's just an array of 100 characters.
You can make it an array of arrays, i.e. char ln[5][100] which will give you room for five lines of 100 characters each.
Then you of course need to index into that array in the loop, i.e.:
for(int i = 0; i < 5; ++i)
{
if(fgets(ln[i], sizeof ln[i], myfile) == NULL)
{
fprintf(stderr, "Read error on line %d\n", i);
exit(1);
}
}
This uses fgets() which is much better suited at reading in whole lines; fscanf() will stop at whitespace with %s which is seldom what you want.
There is no need to use the ampersand in the scanf while getting the string. Make that into like this.
fscanf(myfile,"%s",&ch[i]);
to
fscanf(myfile,"%s",ch);
&ch[i] It will get the character for i th position in that array. If you want to get like that you can use the %c instead of %s. And change this one to.
printf("\n%s", ch);
While printing the string when you use the ampersand(&) that will access the address of that variable.
The program developed must be able to read the input files containing matrix A and matrix B
using fopen function
a. Matrix A and B of different size may be stored in different input file (if required).
Scan and assign matrix A and B as array using fscanf function and for loop
Perform matrix operations
a. Add matrix A and B
b. Subtract matrix A and B
c. Multiply matrix A and B
Use conditional statement if or switch for switching between 3, 4 and 5 elements matrix.
Print all input matrices and results obtained in a new file called output.dat using fprintf
function.
The output.dat file must have a header with the following information:
a. Student name
b. Student matric number
c. Class section
d. Lecturer name
e. Project title
Below the header, the output file must contain matrix A and B and the results from matrix
operation.
Use matrix A and B as given below:
My code reads input in the following format:
The first line has just a number
The other lines have a number and 4 strings
The first line tells the number of following lines.
After reading the file, I want to verify if the number of lines read is the same as specified in the first line. In order to achieve it, I am trying to use a variable count_lines, incrementing it at each iteration of the while loop.
FILE *fp;
char line[MAXLINELEN];
int count_lines = 0;
char city[50], continent[13], cultural[1], outdoors[1];
int total_lines, id;
...
while(fgets(line, sizeof(line), fp))
{
if (count_lines == 0)
{
sscanf(line, "%d", &total_lines);
nodes2 = calloc(sizeof(node), total_lines);
}
else if (sscanf(line, "%d %s %s %s %s", ...)
{
/* code (previously some malloc and strcopy stuff, but the error occurs even without this part of the code) */
}
else
{
/* code */
}
count_lines++;
printf("point \n");
printf("%d\n", count_lines);
}
Data example:
-bash-4.1$ cat places
3
1 City1 Continent1 Y Y
2 City2 Continent1 Y Y
3 City3 Continent1 Y N
However, this is the output of running the code:
point
1
point
1
point
1
point
1
point
1
point
1
point
1
point
1
point
1
point
1
point
1
point
1
I verified that the problem has to do with the else if part. If I comment this part, the counting works correctly. However, I could not figure out why this is happening.
What's wrong with the code?
Note: As this is part of an assignment, I cannot post the whole code.
I omitted irrelevant parts with a /* code */ comment.
strcpy copies second argumet to first argument. In your code you seem to assume the reverse
char *cont_temp = malloc(strlen(continent) + 1);
strcpy(city, cont_temp);
In this case you are copying from cont_temp to city. But cont_temp at this point contains garbage, while city contains the data you just read from file. That's one of the problems. Apparently it should be
strcpy(cont_temp, city);
shouldn't it?
However, I don't understand why you use strlen(continent) to determine the memory size, but then suddenly switch to working with city. That's another problem.
The problem is that cultural and outdoors have size 1, so there's no enough space for the new line character. Defining them with size 2 solves the problem.
I would like to store information from file in structure. My file consists of rows (each row has to be different structure) and columns, each column is different data. File looks like this:
1 AB
2 CD
3 CD
4 AB
My structure is this (where node number is first integer and node type is two letter):
struct nodes{
int nodeNumber;
char nodeType[2];
};
My code so far is this:
lines = lineCount(nodes); //calculates how many lines file has
struct nodes node[lines]; //creates structure array
no = fopen(nodes, mode);
if(no == NULL){
printf("Can't find the files.");
exit(1);
}else{
for(i = 0; i < lines; i++){
fscanf(no, "%d %2c \n", &id, current);
node[i].nodeNumber = id;
strcpy(node[i].nodeType, current);
}
}
when i debug current value is this: current = \"AB\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\" rather than just AB
any ideas?
The problem is your use of strcpy. It copies string, i.e. character arrays with a terminator. This means that strcpy will copy until it sees the string terminator character '\0' and put that at the end of the array, which means you will overwrite one byte outside of the array.
Either use manual copying character by character, a function such as memcpy, or increase the size of the array to three so it can fit the terminating character (which means you have to make sure the definition of current is also of size three, with a string terminator).
scanf does not nul-terminate characters read with the %c format code. (Although apparently current has lots of NULs, I don't know if you can count on that.
You should declare current as char[2], and use memcpy with a length of 2 instead of strcpy.