I have a string in the format:
char *sampleLine = "name1: 251 name2: 23 name3: -67 name4: 0.00 name5: 310 name6: 410 name7: 54001 name8: 332 name9: SOME_TEXT name10: 3 name1: 181 235 237 name11: 11 name12: 240 241 242 243 244 245 246 247 248 249 250 name13: 0 name14: 2 name15: 1 name16: 0 name17: 6 name18: 0 name19: 500 name20: 200 name21: 64 name22: 1 name23: 6 name24: 0 name25: 0";
One of the issues with the string is that some of the names are repeated but the basic pattern seemed to be name: value. So I wrote an algorithm that would take a name and return a value but it doesn't seem to work and does not take into account the issue with a name being repeated.
So for example: if I pass in name1, I would expect to get 251 ,etc.
Here is the code with a sample main:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>
char* extractValue(char* name, char* buffer)
{
char* begining = strstr(buffer,name);
begining += strlen(name) + 2;
if (begining != NULL)
{
char* end = strstr(begining,":");
if (end != NULL)
{
end += 1;
for (int i=0; i < strlen(end); i++)
{
if (end[i] != ':')
{
i++;
} else {
char namevalue[200];
bzero(namevalue,200);
strncpy(namevalue,begining,i);
for (int x=strlen(namevalue); x>0; x--)
{
if (namevalue[x] == ' ')
{
char* value = (char*)malloc(200);
bzero(value,200);
strncpy(value,namevalue,strlen(namevalue) - (strlen(namevalue) - x));
return value;
}
}
break;
}
}
}
}
return NULL;
}
int main (int argc, char** argv)
{
char *sampleLine = "name1: 251 name2: 23 name3: -67 name4: 0.00 name5: 310 name6: 410 name7: 54001 name8: 332 name9: SOME_TEXT name10: 3 name1: 181 235 237 name11: 11 name12: 240 241 242 243 244 245 246 247 248 249 250 name13: 0 name14: 2 name15: 1 name16: 0 name17: 6 name18: 0 name19: 500 name20: 200 name21: 64 name22: 1 name23: 6 name24: 0 name25: 0";
char* value1 = extractValue("name1", sampleLine);
char* value3 = extractValue("name3", sampleLine);
char* value17 = extractValue("name17", sampleLine);
printf("value 1 = %s\n",value1);
printf("value 3 = %s\n",value3);
printf("value 17 = %s\n",value17);
return 0;
}
When I run it, I get:
$ gcc -Wall -std=c99 -o parse parse.c && ./parse
value 1 = 251 name2: 23
value 3 = -67 name4: 0.00
value 17 = 6 name18: 0 name19: 500 name20: 200 name21:
Instead of expected
value 1 = 251
value 3 = -67
value 17 = 6
Two subtle errors.
First,
if (end[i] != ':')
{
i++;
} else ..
By manually incrementing i here, you are skipping a character, as i already gets incremented by the for-loop. It appears to have no side effects, but only because ...
Second: the actual cause of your problem is you are measuring the length of the wrong string. You locate the beginning of the name value (begining) and then its end by scanning forward from that position for the next :. Then, you track backwards to find the previous space, which should be the end of the value. But ...
for (i=0; i < strlen(end); i++)
checks forwards from the (already determined) end of the string! Of course, for your test names, you are bound to find a colon somewhere further along--but its position has nothing to do with the string you are interested in, which is between begining and end.
Change your i loop to
for (i=0; i < end-begining; i++)
and change the : check to
if (begining[i] == ':')
{
char namevalue[200];
... (etc.)
(discarding the i++ line).
Loose notes
A slightly faster way to look for a single character is strchr:
char* end = strchr(begining,':');
You might want to find a better strategy for locating the name. If you are looking for name1, it could find name12 as well as noname1.
One way would be to split a string into tokens using strtok. Then anything ending with a : is a potential name, and the next token is the value you are looking for. Omitted, because it's a nice exercise in its own. (And if you are going to try this: strtok modifies the original string!)
Finally, you can do without all those loops :-)
char* extractValue(char* name, char* buffer)
{
char *start, *end, *ret_val;
int length;
char* begining = strstr(buffer,name);
if (!begining)
return NULL;
start = begining + strlen(name);
if (start[0] != ':')
return NULL;
start++;
// skip initial spaces, if any
while (*start == ' ')
start++;
// ptr points to the start of data. Find end.
end = start;
while (*end && *end != ' ')
end++;
// we have the correct string in start..end
length = end-start;
// it's a zero-terminated string so add 1 for the zero
ret_val = (char *)malloc(length+1);
strncpy (ret_val, start, length);
// put the zero where it belongs
ret_val[length] = 0;
return ret_val;
}
Related
I'm reading a .pgm file (like the lines below) with "fgetc(file)". When getting only the numbers with a loop in which I avoid the spaces in between (it seems it treats each space, no matter how big it is, as a single character), it joints the last number of a line and the first one from the following line (ex, 146 last number and 105 first number, it gives 146105).
113 116 97 124 146
105 100 112 98 88
100 117 98 87 126
131 101 87 137 161
When simply printing the contents of the file, I get a lot of spaces on the change of line in the console, like this:
113 116 97 124 146
105
When printing the contents, each character on a single line, i get this other output:
9
7
//one line
1
2
4
//one line
1
4
6
//change of linne in the file, two lines here!!!!
1
0
5
//one line
1
0
0
Any ideas about how I should treat this part of the file?
Here is my code:
int get_number(int current[4], int n)
{
int final_number, index = 0, max = n;
while (index < max)
{
final_number += current[index] * pow(10, (n-1));
index++;
n --;
}
return final_number;
}
file = fopen("baboon.pgm", "r");
int info = fgetc(file), n;
while (info != EOF)
{
n = 0;
while (info != ' ' || info != ' ' || info != ' ' || info != ' ')
{
printf("%c", info);
int current_number[4];
n++;
}
if (current_number[0] != 0)
{
printf("%d ", get_number(current_number, n));
}
info = fgetc(file);
}
I think that with this piece of the code you can get an idea. If need more, say it. I also leave you here a link to download the image file if you want: https://drive.google.com/file/d/1ZYIU6fcUOnhRND2zph5MUr8545P6U8bX/view?usp=sharing
I have a program that outputs a huge array of integers to stdout, each integer in a line. Ex:
103
104
105
107
I need to write another program that reads in that array and fill up the spaces where the number isn't an increment of 1 of the previous number. The only different between numbers is going to be 2 (105,107), which makes it easier.
This is my code to do that logic:
printf("d",num1);
if ((num2-num1) != 1)
numbetween = num1 + 1;
printf("%d", numbetween);
printf("%d", num2);
else(
printf("%d",num2);
)
So the output of this program will now be:
103
104
105
106
107
My issue is reading the numbers. I know I can do while (scanf("%hd", &num) != EOF) to read all the lines one at a time. But to do the logic that I want, I'm going to need to read two lines at a time and do computation with them, and I don't know how.
You could always just read the first and last numbers from the file, and then print everything in between.
int main( void )
{
// get the first value in the file
int start;
if ( scanf( "%d", &start ) != 1 )
exit( 1 );
// get the last value in the file
int end = start;
while ( scanf( "%d", &end ) == 1 )
;
// print the list of numbers
for ( int i = start; i <= end; i++ )
printf( "%d\n", i );
}
Read first num then add missing if needed when you read next int
#include <stdio.h>
#include <stdlib.h>
int main()
{
int previous = 0;
int num;
scanf("%hd", &previous);
while (scanf("%hd", &num) != EOF) {
for (int i = previous; i < num; i++) {
printf("%d\n" , i);
}
previous = num;
}
printf("%d\n" , previous);
return 0;
}
this input
100
102
103
105
107
110
returns this output
100
101
102
103
104
105
106
107
108
109
110
While you can read the first and last, to fill the range, what you are really doing is finding the min and max and printing all values between them inclusively. Below the names are left first and last, but they represent min and max and will cover your range regardless whether the values are entered in order. Taking that into consideration, another approach insuring you cover the limits of the range of int would be:
#include <stdio.h>
int main (void) {
int num = 0;
int first = (1U << 31) - 1; /* INT_MAX */
int last = (-first - 1); /* INT_MIN */
/* read all values saving only first (min) and last (max) */
while (scanf (" %d", &num) != EOF) {
first = num < first ? num : first;
last = num > last ? num : last;
}
/* print all values first -> last */
for (num = first; num <= last; num++)
printf ("%d\n", num);
return 0;
}
Input
$ cat dat/firstlast.txt
21
25
29
33
37
41
45
49
53
57
61
65
69
73
77
81
85
89
93
97
101
Output
$ ./bin/firstlast < dat/firstlast.txt
21
22
23
24
25
26
27
28
29
<snip>
94
95
96
97
98
99
100
101
Note: you can change the types to conform to your expected range of data.
I have to copy the elements of one array of structure to blank elements of a new array of structures (all dynamically allocated). Every element of the array of structures I have, structure 'a', has only two columns, left_column and right_column. Some of the right column entries of each element of structure a (say, i'th structure element) matches the left column entry of the next (viz., i+1 th) structure element of the same structure a. I am attempting to find such matching entries and I am attempting to copy the entire left and right column of the matching elements one-by-one to a smaller, conserved structure, structure b. The problem is the code is compiling, but it is not getting into the all-important matching part, viz., the if part. It is getting into the while loop.
Kept below are the information and sample data. This code has come to this stage due to 'PlerumCodeExperientia', I thank him. Please suggest how to copy these matching elements.
Thanking you, Dan.
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char* args[])
{
struct a
{
int left_line;
int right_line;
};
struct b
{
int conserved_left;
int conserved_right;
};
FILE *fp100; // Output File
fp100 = fopen("Conserved_Elements.txt", "a");
struct a *ptr1;
int structACapacity = 3; // Only 3 such comparison files are being worked with, there are >1000 comparison files
ptr1 = malloc(structACapacity*sizeof(struct a));
struct b *ptr2;
int structBCapacity = 1000;
ptr2 = malloc(structBCapacity*sizeof(struct b));
int structure_ctr;
int number_of_line_comparison_files = 3; // Only 3 for the time being
int knt;
int left, right;
for (structure_ctr=0; structure_ctr < number_of_line_comparison_files; structure_ctr++) {
knt = 0;
while (((ptr1+knt) < (ptr1+structACapacity-1)) && (knt < 500)) {
fprintf(fp100, "Getting Into While\n");
// finding the matching entries between right column of knt and left column of (knt+1)
if ((ptr1+knt)->right_line == (ptr1+(1+knt))->left_line) {
fprintf(fp100,"\tGetting Into the If\n");
// copying matching values to the struct b
left = (ptr2+knt)->conserved_left = (ptr1+knt)->left_line;
right = (ptr2+knt)->conserved_right = (ptr1+knt)->right_line;
//fprintf(fp100,"C-Left:%d\tC-Right:%d\tLeft%d\tRight%d\n",(ptr2+knt)->conserved_left,(ptr2+knt)->conserved_right,left,right);
// left, right are there for convinience only - easier to see, same values
fprintf(fp100,"C-Left:%d\tC-Right:%d\n", left,right);
}
++knt;
} // end of while
} //end of for
}
The files look:
A fragment of the first structure element looks like:
17 216
26 119
28 16
29 122
59 124
60 116
62 114
63 112
66 61
69 54
70 51
71 62
91 40
99 38
A fragment of the Second element looks like:
321 25
110 45
116 49
216 110
56 117
54 131
32 167
31 178
8 188
12 199
39 239
60 244
121 263
124 275
A fragment of the 3rd element looks like:
75 223
61 248
45 278
31 290
10 291
111 311
117 324
128 338
139 347
148 365
167 376
178 381
191 394
193 397
etc..., there are many such elements. All of them contain such unformatted two columns of integers.
In case if you are interested to see how the content of the original file was loaded into 'structure_a', the next piece is given. It works fine.
for(q=0; q < number_of_line_comparison_files; q++) // going through the total number of files
{
// File Name Etc ..
while (fgets(file_line,99,line_comparison_file)!= NULL)
{
++number_of_lines ; // Integer
for(j=0;j<6;j++)
string_left_line[j]=file_line[j];
for(j=0;j<6;j++)
string_right_line[j]=file_line[6+j];
left_line = atoi(string_left_line);
right_line = atoi(string_right_line);
*(&(ptr1+q)->left_line) = left_line;
*(&(ptr1+q)->right_line) = right_line;
fprintf(fp100,"Left:%d\tRight:%d\n",(ptr1+q)->left_line,(ptr1+q)->right_line);
} // END OF THE 'WHILE'
fprintf(fp100,"\n\n\t================================== ================================\n\n");
} // End of For
Dan
I must say that, there should be a little more information, for the question to be completely clear.
With the given data, this is my answer. At least the part of what I assume is asked.
I hope it helps.
// copy_pointer_struct.c
#include<stdio.h>
#include<stdlib.h>
int main(int argc, char* args[])
{
struct a
{
int left_line;
int right_line;
};
struct b
{
int conserved_left;
int conserved_right;
};
FILE *fp100;
fp100 = fopen("struct_file.txt", "a");
struct a* ptr1;
int structACapacity = 3;
ptr1=(struct a*)malloc(structACapacity*sizeof(struct a));
struct b *ptr2;
int structBCapacity = 1000;
ptr2=(struct b*)malloc(structBCapacity*sizeof(struct b));
// for writing test values to ptr1 array
int i;
for ( i = 0; i < structACapacity; i++ )
{
ptr1[i].left_line = i;
(ptr1+i)->right_line = i+1;
}
int structure_ctr,
number_of_line_comparison_files = 10,
knt;
// This outer for is neccessary only if you are getting structs form another source - a file for example or another structure.
//for(structure_ctr=0; structure_ctr < number_of_line_comparison_files; structure_ctr++)
{
// this inner for would be neccessary if you had an 2 dimensional array of structs or a pointer to a pointer to struct.
//for(knt=0; knt<500; knt++)
{
knt = 0;
// in your while condition there is no changing value, (change being made inside cycle or condition itself),
// which results in an infinite (for condition true) cycle or 0 cycles (for condition false)
// this particular condition works until we have reached 500th element or the end of array,
// whichever has lower value.
// Of course in case of use of outer for ( && knt < 500) wouldn't be used, depending of the goal you have.
while( (ptr1+knt) < (ptr1+structACapacity-1) && knt < 500 )
{
if( (ptr1+knt)->right_line == (ptr1+1+knt)->left_line ) // comment line for file test
{
// copying duplicate values to the struct b
int left = (ptr2+knt)->conserved_left = (ptr1+1+knt)->left_line;
int right = (ptr2+knt)->conserved_right = (ptr1+knt)->right_line;
// here you can write those values to a file as 2 integers, for example
fprintf(fp100,"%d %d\n", left, right);
}
++knt;
} // while
}//
} //for structure_ctr
fclose(fp100);
}
Perhaps this addition helps:
// copy_pointer_struct.c
#include<stdio.h>
#include<stdlib.h>
typedef struct a
{
int left_line;
int right_line;
} structA;
typedef struct b
{
int conserved_left;
int conserved_right;
} structB;
int fillColumnPtr(FILE* source, structA* ptr);
int main(int argc, char* args[])
{
FILE *fp100;
fp100 = fopen("struct_file.txt", "w");
structA* ptr1;
int structACapacity = 1000;
ptr1=(structA*)malloc(structACapacity*sizeof(struct a));
printf("kapacitet ptr1: %d\n", sizeof ptr1);
structB *ptr2;
int structBCapacity = 1000;
ptr2=(struct b*)malloc(structBCapacity*sizeof(struct b));
char *filename = "columns_file4.txt";
FILE *cfile1 = fopen(filename, "r");
printf("Loading values from file: %s . . . \n", filename);
int number_of_lines = fillColumnPtr(cfile1, ptr1);
fclose(cfile1);
printf("Done.\n\n");
printf("Values loaded to ptr1(total lines %d):\n", number_of_lines);
int i;
for ( i = 0; i < number_of_lines; i++ )
{
printf("left: %6d, right: %6d\n", ptr1[i].left_line, ptr1[i].right_line);
}
printf("\nProcessing...\n");
int structure_ctr,
number_of_line_comparison_files = 10,
knt;
knt = 0;
while( (ptr1+knt) < (ptr1+structACapacity-1) && knt < number_of_lines )
{
if( (ptr1+knt)->right_line == (ptr1+1+knt)->left_line ) // comment line for file test
{
// copying duplicate values to the struct b
int left = (ptr2+knt)->conserved_left = (ptr1+1+knt)->left_line;
int right = (ptr2+knt)->conserved_right = (ptr1+knt)->right_line;
// here you can write those values to a file as 2 integers, for example
fprintf(fp100,"%d %d\n", left, right);
printf("%d %d\n", left, right);
}
++knt;
} // while
fclose(fp100);
}
// function: transfers data from a source file to pointer to struct
int fillColumnPtr(FILE* source, structA* ptr)
{
char file_line[20],
*str_left_line = calloc(sizeof(char), 6),
str_right_line[6];
int left_line, right_line, j, line_counter = 0, i = 0;
while ( fgets(file_line, 19, source) != NULL )
{
printf(">> fileline: %s", file_line);
for(j=0;j<6;j++)
{
str_left_line[j]=file_line[j];
str_right_line[j]=file_line[6+j];
}
left_line = atoi(str_left_line);
right_line = atoi(str_right_line);
printf(" left right: %-3d %6d\n", left_line, right_line);
ptr[i].left_line = left_line;
ptr[i].right_line = right_line;
++i;
++line_counter;
}
return line_counter;
}
Note: I examined few of your source values, that are supposed to be in a file - non of them satisfies the condition inside if, resulting in an empty pointer.
The additional posted, I have tested with altered values and it works.
For this method check the spacing in rows.
Contents of the "columns_file4.txt":
321 25
25 45
116 49
216 110
110 117
54 131
32 167
31 178
178 188
12 199
199 239
60 244
121 263
124 275
// End of file
In this file there are equal values for example:
(row 1 col right)25 == (row 2 col left )25, 110 , 178, 199.
If this is not what you are looking for, then alter the if condition.
Good luck.
Hope this help.
This code is meant to read the value from an image file into an array (I know the size is 16*8).
When I dynamically create the img array so I can have any size image it crashes when run, when I manually make it the correct size (char img[16][8];) it works.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main()
{
FILE *fin;
fin= fopen ("test.pgm","rb");
if (fin == NULL)
{
printf ("ERROR");
fclose(fin);
}
int i=0,j=0,u=16,v=8,d;
char test[20];
char k;
char c[10];
while((k=fgetc(fin))!='\n')
{
test[j]=k;
j=j+1;
}
char **img = (char**) calloc(u,sizeof(char*));
for ( i = 0; i < u; i++ )
{
img[i] = (char*) calloc(v,sizeof(char));
}
fread(img,1,(u*v),fin);
for (i=0; i<u; i++)
{
for (j=0; j<v; j++)
{
printf("%d ",img[i][j]);
}
printf("\n");
}
fclose(fin);
}
Since you are dynamically allocating 16 separate 8 byte arrays, you will then need to compute 16 individual reads into each of those arrays. (I have removed the unnecessary, and potentially bug prone, casts to calloc()).
char **img = calloc(u,sizeof(char*));
for ( i = 0; i < u; i++ )
{
img[i] = calloc(v,sizeof(char));
fread(img[i],1,v,fin);
}
/*fread(img,1,(u*v),fin);*/
The single fread() call you had works for char img[16][8], because in that case, img consists of contiguous memory sized at 16 * 8 bytes. But, that call will not work for the way you have created your dynamically allocated array, since img is now an array of pointers, and so the fread() call you have will overwrite those pointer values with data from the file.
If you want to do a single call to fread(), then you can change your dynamic allocation (and combine with VLA)
char (*img)[v];
img = malloc(u * sizeof(*img));
fread(img,1,(u*v),fin);
This declares img to be a pointer to an array v of char (v was initialized to 8). It then allocates u (ie, 16) many of array v of char in a contiguous allocation for img. Now, img can be used for the single fread() call like you had for char img[16][8], and also preserves the same "2D" addressing of img as well.
The answer by jxh correctly diagnoses the trouble with the original code, which this answer does not (in part because of that). It also demonstrates the power of variable length arrays, VLAs, which were added to C99. It is really neat and should be accepted.
If you are stuck with C89 (perhaps because you work on Windows with MSVC), then you can still do the single read if you allocate the space contiguously. However, if you're also going to use the double index notation, you still need the array of pointers, or you will need to use the notation img[i*v+j] (and a different type for img). This code implements the extra array of pointers, and also includes a variety of other minor bug fixes to the original code (the most important being that it returns after failing to open the file, rather than reporting 'ERROR' and continuing as if nothing had gone wrong, including attempting to fclose() a null pointer, which is good for a crash).
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
const char *filename = "test.pgm";
FILE *fin = fopen(filename, "rb");
if (fin == NULL)
{
fprintf(stderr, "ERROR opening file %s\n", filename);
return(1);
}
int i;
int j = 0;
int u=16;
int v=8;
char test[20];
int k;
while ((k = fgetc(fin)) != '\n')
test[j++] = k;
test[j] = '\0';
printf("test: %s\n", test);
char **img = (char**) calloc(u,sizeof(char*));
char *space = (char *)calloc(u*v, sizeof(char));
for (i = 0; i < u; i++)
img[i] = &space[v*i];
if (fread(img[0], 1, (u*v), fin) != (size_t)(u*v))
{
fprintf(stderr, "Error: short read\n");
return(1);
}
for (i = 0; i < u; i++)
{
for (j = 0; j < v; j++)
printf("%3d ", img[i][j]);
printf("\n");
}
fclose(fin);
free(img[0]);
free(img);
return(0);
}
Note that the loop reading into test is not properly error checked; it could overflow, and it doesn't detect EOF, either.
Input data:
abcdefghij
aaaaaaa
bbbbbbb
ccccccc
ddddddd
eeeeeee
fffffff
ggggggg
hhhhhhh
iiiiiii
jjjjjjj
kkkkkkk
lllllll
mmmmmmm
nnnnnnn
ooooooo
ppppppp
Output data:
test: abcdefghij
97 97 97 97 97 97 97 10
98 98 98 98 98 98 98 10
99 99 99 99 99 99 99 10
100 100 100 100 100 100 100 10
101 101 101 101 101 101 101 10
102 102 102 102 102 102 102 10
103 103 103 103 103 103 103 10
104 104 104 104 104 104 104 10
105 105 105 105 105 105 105 10
106 106 106 106 106 106 106 10
107 107 107 107 107 107 107 10
108 108 108 108 108 108 108 10
109 109 109 109 109 109 109 10
110 110 110 110 110 110 110 10
111 111 111 111 111 111 111 10
112 112 112 112 112 112 112 10
You fread into your array of pointers but they point to various places in memory so that will not work.
In order for it to work set pointers to point to the same block but at different offsets
so instead of
char **img = calloc(u,sizeof(char*));
for ( i = 0; i < u; i++ )
{
img[i] = calloc(v,sizeof(char));
}
do
char **img = calloc(u,sizeof(char*));
char *block = calloc(u*v,sizeof(char);
for ( i = 0; i < u; i++ )
{
img[i] = block + v*i;
}
then
fread(block,1,(u*v),fin);
I want to open a text file (see below), read the first int in every line and store it in an array, but I get an segmentation fault. I got rid of all gcc warnings, I read through several tutorials I found on the net and searched stackoverflow for solutions, but I could't make out, what I am doing wrong.
It works when I have everything in the main function (see example 1), but not when I transfer it to second function (see example 2 further down). In example 2 I get, when I interpret gdb correctly a seg fault at sscanf (line,"%i",classes[i]);.
I'm afraid, it could be something trivial, but I already wasted one day on it.
Thanks in advance.
[Example 1] Even though that works with everything in main:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
const int LENGTH = 1024;
int main() {
char *filename="somedatafile.txt";
int *classes;
int lines;
FILE *pfile = NULL;
char line[LENGTH];
pfile=fopen(filename,"r");
int numlines=0;
char *p;
while(fgets(line,LENGTH,pfile)){
numlines++;
}
rewind(pfile);
classes=(int *)malloc(numlines*sizeof(int));
if(classes == NULL){
printf("\nMemory error.");
exit(1);
}
int i=0;
while(fgets(line,LENGTH,pfile)){
printf("\n");
p = strtok (line," ");
p = strtok (NULL, ", ");
sscanf (line,"%i",&classes[i]);
i++;
}
fclose(pfile);
return 1;
}
[Example 2] This does not with the functionality transfered to a function:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
const int LENGTH = 1024;
void read_data(int **classes,int *lines, char *filename){
FILE *pfile = NULL;
char line[LENGTH];
pfile=fopen(filename,"r");
int numlines=0;
char *p;
while(fgets(line,LENGTH,pfile)){
numlines++;
}
rewind(pfile);
* classes=(int *)malloc(numlines*sizeof(int));
if(*classes == NULL){
printf("\nMemory error.");
exit(1);
}
int i=0;
while(fgets(line,LENGTH,pfile)){
printf("\n");
p = strtok (line," ");
p = strtok (NULL, ", ");
sscanf (line,"%i",classes[i]);
i++;
}
fclose(pfile);
*lines=numlines;
}
int main() {
char *filename="somedatafile.txt";
int *classes;
int lines;
read_data(&classes, &lines,filename) ;
for(int i=0;i<lines;i++){
printf("\nclasses[i]=%i",classes[i]);
}
return 1;
}
[Content of somedatafile.txt]
50 21 77 0 28 0 27 48 22 2
55 0 92 0 0 26 36 92 56 4
53 0 82 0 52 -5 29 30 2 1
37 0 76 0 28 18 40 48 8 1
37 0 79 0 34 -26 43 46 2 1
85 0 88 -4 6 1 3 83 80 5
56 0 81 0 -4 11 25 86 62 4
55 -1 95 -3 54 -4 40 41 2 1
53 8 77 0 28 0 23 48 24 4
37 0 101 -7 28 0 64 73 8 1
...
This:
sscanf (line,"%i",classes[i]);
is probably wrong. You need to dereference there too, try:
sscanf (line,"%i", &(*classes)[i]);
This is because classes is a pointer to an array of integers. You want the address of one of those integers, so that sscanf() can write the parsed number there. Therefore, you must first dereference classes to get the array, then say that you want the address of element number i in that array.
You could also use
sscanf (line,"%i", *classes + i);
Which might be clearer, depending on how comfortable you are with these things.
The problem is you're applying the [] operator to an int* in the first case and an int** in the second. The int** is like a 2d array, when you use the [] operator in conjunction with the int** you are indexing into an array of int*. In your case this is not what you want, because you only initialize the first the first entry in this array. So when you access classes[1] it will crash because it's uninitialized. You could avoid yourself this confusion by passing in the pointer as a reference instead of a double pointer:
int*& classes instead of int** classes
Then you could use the same code as from your main function.