I have to read a file like this:
0 -> 1:50 2:30 3:10
1 ->
2 -> 0:10 3:20
3 -> 1:20 2:10 3:30
Here's my code:
graphs = fopen(argv[2],"r");
if(graphs==NULL){
printf("File hostgraphs not found\n");
exit(EXIT_FAILURE);
}
while((err=fscanf(graphs,"%d ->",&num))==1){
row=num;
while((err1=fscanf(graphs," %d:%d ",&column,&visits))==2){
hostgraphs[row*n+column]=visits;
}
if(err1!=2)
break;
if(err==0){
printf("Hostgraph out of bounds\n");
exit(EXIT_FAILURE);
}
}
for(i=0;i<n;i++){
for(j=0;j<n;j++){
printf("%d ", hostgraphs[i*n+j]);
}
printf("\n");
}
It gives me the following result:
0 50 30 10
0 0 0 0
0 0 0 0
0 0 0 0
The expected output must be:
0 50 30 10
0 0 0 0
10 0 0 20
0 20 10 30
Can anyone help me please?
You can do this by reading the file, one line at a time, using getline, and then applying the same logic, as you are doing, on each line separately.
In the following code, I first get a single line from the file in buffer using getline method. Then I process that line as a FILE pointer fbuffer using fmemopen method, which is used to read a string like a file:
graphs = fopen(argv[2],"r");
if(graphs==NULL)
{
printf("File hostgraphs not found\n");
exit(EXIT_FAILURE);
}
char *buffer = NULL;
size_t len = 0;
while(getline(&buffer, &len, graphs) != -1)
{
FILE * fbuffer = fmemopen(buffer, len, "r");
while((err=fscanf(fbuffer,"%d -> ",&num))==1)
{
row=num;
while((err1=fscanf(fbuffer," %d:%d ",&column,&visits))==2)
{
hostgraphs[row*n+column]=visits;
}
if(err1!=2)
{
break;
}
if(err==0)
{
printf("Hostgraph out of bounds\n");
exit(EXIT_FAILURE);
}
}
free(buffer);
buffer = NULL;
len = 0;
}
for(i=0;i<n;i++)
{
for(j=0;j<n;j++)
{
printf("%d ", hostgraphs[i*n+j]);
}
printf("\n");
}
Note: I have just added code to make your existing code work, without making any changes to your code.
The fix is simple: remove the trailing space in the fscanf format string in
fscanf(graphs," %d:%d ",&column,&visits)
It should be simplified as
fscanf(graphs,"%d:%d", &column, &visits)
fscanf ignores the newline then after read first row, it moves to next row and read 5 and results 1 in err1. That is the root-cause. You can add fseek to move back and start new sequence as bellow code-snip or simply change the algorithm to another effective one.
graphs = fopen(argv[2],"r");
if (!graphs) {
printf("File hostgraphs not found<%s>\n", argv[1]);
exit(EXIT_FAILURE);
}
while((err = fscanf(graphs, "%d ->", &num)) == 1) {
pos = ftell(graphs); // save position
while((err1 = fscanf(graphs, " %d:%d", &column, &visits)) == 2 ) {
hostgraphs[num * n + column] = visits;
pos = ftell(graphs); // save position
}
// seek back to previous one and start new sequence
fseek ( graphs , pos, SEEK_SET );
}
for(i = 0; i< n; i++){
for(j = 0; j < n; j++){
printf("%d ", hostgraphs[i * n + j]);
}
printf("\n");
}
You were close, but you needed a way of locating each '\n' without reading the next row value from the file. That is very difficult to do with fscanf where you have varying number of elements in each row in your input file.
Another approach is to use fgets to read the entire line, and then separate the initial "row -> " prefix from the data values. If you move the values into a separate values buffer (say vbuf), you can then repeatedly loop through the buffer by finding the space, advancing to the next digit and then using sscanf to split the column and visits.
(you actually don't even need to split the values in vbuf, you can simply use a pointer to advance past the "row -> " text working with the entire line.)
The following example puts those pieces together and parses the values into the correct positions in hostgraphs. Look it over and let me know if you have questions:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
enum { COLS = 4, MAXH = 16, MAXC = 64 };
int main (int argc, char **argv) {
char buf[MAXC] = "", vbuf[MAXC] = "";
char *p = NULL, *rfmt = "%d -> %[^\n]";
int row, column, visits, hostgraphs[MAXH] = {0};
size_t i, j, n = 0;
FILE *graphs = argc > 1 ? fopen (argv[1], "r") : stdin;
if (!graphs) {
fprintf (stderr, "error: file open failed '%s'.\n", argv[1]);
return 1;
}
while (fgets (buf, MAXC, graphs))
{
*vbuf = 0; /* initialize vbuf, split %d:%d pars into vbuf */
if (sscanf (buf, rfmt, &row, vbuf) < 1)
break;
if (!*vbuf) { /* check vbuf contians values */
n++;
continue;
}
/* read 1st pair */
if (sscanf (vbuf, "%d:%d", &column, &visits) != 2) {
fprintf (stderr, "error: invalid line format\n");
exit (EXIT_FAILURE);
}
hostgraphs[row*COLS+column] = visits;
p = vbuf; /* assign p, parse remaining pairs */
while ((p = strchr (p, ' '))) /* find space */
{
while (*p < '0' || '9' < *p) /* find digit */
p++;
if (sscanf (p, "%d:%d", &column, &visits) == 2)
hostgraphs[row*COLS+column] = visits;
}
n++; /* advance row count */
}
for (i = 0; i < n; i++) { /* output values */
printf (" row[%2zu] : ", i);
for(j = 0; j < COLS; j++) {
printf (" %2d", hostgraphs[i * COLS + j]);
}
printf ("\n");
}
if (graphs != stdin)
fclose (graphs);
return 0;
}
Input File
$ cat ../dat/hostgraph.txt
0 -> 1:50 2:30 3:10
1 ->
2 -> 0:10 3:20
3 -> 1:20 2:10 3:30
Output
$ ./bin/hostgraph < ../dat/hostgraph.txt
row[ 0] : 0 50 30 10
row[ 1] : 0 0 0 0
row[ 2] : 10 0 0 20
row[ 3] : 0 20 10 30
Related
I've been having trouble with a program. The first number in the file is the number of "sets" the program needs to run. For every set, I need it to read the next 6 integers, split into two groups. For example, with this data set:
{3, 4, 6, 8, 5, 5, 7, 9, 8, 7, 2, 4, 5, 6, 9, 1, 5, 7, 6}
The program should run 3 sets. In set one, it needs to read the next three integers in one group, then the next three integers in the other group, then move to the next set. So
Set 1:
[4, 6, 8] = 18
[5, 5, 7] = 17
Set 2:
[9, 8, 7] = 24
[2, 4, 5] = 11
Set 3:
[6, 9, 1] = 16
[5, 7, 6] = 18
I'm honestly not sure where to start. I've managed to get it to read the first number as the set number, but I'm not sure how to group the integers the way I need it to.
Here's the code so far:
int main(){
int set_number, set_total, points_1, points_2;
int point_total_1 = 0, point_total_2 = 0;
FILE * ifp;
char input_name[50] = "";
printf("Please enter file input name for scores.\n\n");
scanf("%s", &input_name);
ifp = fopen(input_name, "r");
fscanf(ifp, "%d", &set_total);
FILE * ofp = fopen("ninja_scores_output.txt", "w");
for(set_number = 1; set_number <= set_total; set_number++){
fprintf(ofp,"Set #%d:\n", set_number);
fprintf(ofp,"Student 1: %d points.\n\n", points_1);
fprintf(ofp,"Student 2: %d points.\n\n", points_2);
point_total_1 += points_1;
point_total_2 += points_2;
}
fprintf(ofp,"Final Scores:\n"
"Student 1: %d total points.\n\n", point_total_1);
fprintf(ofp,"Student 2: %d total points.\n\n", point_total_2);
if(point_total_1 > point_total_2){
fprintf(ofp, "Student 1 will move onto the next round!");
}
else if(point_total_2 > point_total_1){
fprintf(ofp, "Student 2 will move onto the next round!");
}
fclose(ofp);
fclose(ifp);
return 0;
}
EDIT:
After some tinkering, I managed to get it to read the lines properly, but something's still going wrong. How do I get it to continue down the lines after it finishes it's first loop? In the test file, the values are: {3, 3, 3, 19, 16, 8, 9, 15, 1, 14, 12, 13, 1, 7, 8, 9, 6, 6, 5} (All on new lines). When I run the program, it runs three sets, but in the first set, it's listing student 1 as earning 65 points, while student 2 earned 15 points. In subsequent sets, student 1's score only increases by 6 and student 2 only increases by 15. I'm not sure how to fix it.
Here's the new code:
int main(){
int set_number, set_total, point_val, points_1, points_2;
int point_total_1 = 0, point_total_2 = 0;
FILE * ifp;
char input_name[50] = "";
printf("Please enter file input name for scores.\n\n");
scanf("%s", &input_name);
ifp = fopen(input_name, "r");
FILE * ofp = fopen("ninja_scores_output.txt", "w");
fscanf(ifp, "%d", &set_total);
int current_throw;
int throw_value;
for(set_number = 1; set_number <= set_total; set_number++){
for(current_throw = 1; current_throw <= 6; current_throw++){
fscanf(ifp, "%d", &point_val);
if(current_throw <= 3){
points_1 += current_throw;
}
else{
points_2 += current_throw;
}
}
fprintf(ofp,"Set #%d:\n", set_number);
fprintf(ofp,"Student 1: %d points.\n\n", points_1);
fprintf(ofp,"Student 2: %d points.\n\n", points_2);
point_total_1 += points_1;
point_total_2 += points_2;
}
fprintf(ofp,"Final Scores:\n"
"Student 1: %d total points.\n\n", point_total_1);
fprintf(ofp,"Student 2: %d total points.\n\n", point_total_2);
if(point_total_1 > point_total_2){
fprintf(ofp, "Student 1 will move onto the next round!");
}
else if(point_total_2 > point_total_1){
fprintf(ofp, "Student 2 will move onto the next round!");
}
fclose(ofp);
fclose(ifp);
return 0;
}
If I am following along correctly and you need to read the number of sets from the first line, then each set of six values from the lines that follow (one number per-line), producing the output you show of "Set X" followed by the two groups of three values, then your logic shown isn't going to get you there.
This sort of number of sets, groups within each set and number of groups is one that can be handled fairly simply with nested loops. To read the number of sets, you simply read the first value and then you will loop that number of times. That sets the limits for your outer loop for you. For example to read and setup your outer loop you could do:
#include <stdio.h>
#define SETSZ 6 /* if you need a constant, #define one (or more) */
#define GRPSZ 3
#define NGRPS 2
int main (int argc, char **argv) {
int nsets = 0; /* array holding set */
/* use filename provided as 1st argument (stdin by default) */
FILE *fp = argc > 1 ? fopen (argv[1], "r") : stdin;
if (!fp) { /* validate file open for reading */
perror ("file open failed");
return 1;
}
if (fscanf (fp, "%d", &nsets) != 1) { /* read/VALIDATE nsets */
fputs ("error: invalid format - nsets not read.\n", stderr);
return 1;
}
for (int i = 0; i < nsets; i++) { /* loop nsets times */
int set[SETSZ] = {0}; /* array holding set */
/* process remaining sets here */
}
(note: when taking user input, you must VALIDATE every INPUT by checking the return of the input function used. Otherwise, you are just inviting Undefined Behavior in your code on a matching or input failure)
As you loop over each set, you need to:
fill the set with SETSZ values validating each input,
loop NGRPS times processing GRPSZ values from the set,
find the sum of the GRPSZ values, and
output the data in the format shown
In doing so, you can replace the /* process remaining sets here */ placeholder with:
for (int j = 0; j < SETSZ; j++) { /* loop SETSZ times filling set */
if (fscanf (fp, "%d", &set[j]) != 1) { /* read/VALIDATE set value */
fputs ("error: invalid format in set.\n", stderr);
return 1;
}
}
printf ("\nSet %d\n\n", i + 1); /* output set number */
for (int j = 0; j < NGRPS; j++) { /* loop NGRPS times */
int sum = 0; /* declare sum for group of 3 */
putchar ('['); /* output '[' prefix */
for (int k = 0; k < GRPSZ; k++) { /* loop GRPSZ times */
sum += set[j * GRPSZ + k]; /* sum group values */
printf (k ? ", %d" : "%d", set[j * GRPSZ + k]); /* output values */
}
printf ("] = %d\n", sum); /* output result */
}
Other than closing your file, that is the extent of your program. Note, I am simply outputting values to stdout. If you want to write the values to a file, you can simply redirect the output to an output file, e.g. ./program infile > outfile, or you can open another file stream for output and write the values to the file from within the program -- entirely up to you.
Note the program read from the filename provided as the first argument (or reads from stdin by default if no argument is given). The complete example would be:
#include <stdio.h>
#define SETSZ 6 /* if you need a constant, #define one (or more) */
#define GRPSZ 3
#define NGRPS 2
int main (int argc, char **argv) {
int nsets = 0; /* array holding set */
/* use filename provided as 1st argument (stdin by default) */
FILE *fp = argc > 1 ? fopen (argv[1], "r") : stdin;
if (!fp) { /* validate file open for reading */
perror ("file open failed");
return 1;
}
if (fscanf (fp, "%d", &nsets) != 1) { /* read/VALIDATE nsets */
fputs ("error: invalid format - nsets not read.\n", stderr);
return 1;
}
for (int i = 0; i < nsets; i++) { /* loop nsets times */
int set[SETSZ] = {0}; /* array holding set */
for (int j = 0; j < SETSZ; j++) { /* loop SETSZ times filling set */
if (fscanf (fp, "%d", &set[j]) != 1) { /* read/VALIDATE set value */
fputs ("error: invalid format in set.\n", stderr);
return 1;
}
}
printf ("\nSet %d\n\n", i + 1); /* output set number */
for (int j = 0; j < NGRPS; j++) { /* loop NGRPS times */
int sum = 0; /* declare sum for group of 3 */
putchar ('['); /* output '[' prefix */
for (int k = 0; k < GRPSZ; k++) { /* loop GRPSZ times */
sum += set[j * GRPSZ + k]; /* sum group values */
printf (k ? ", %d" : "%d", set[j * GRPSZ + k]); /* output values */
}
printf ("] = %d\n", sum); /* output result */
}
}
if (fp != stdin) /* close file if not stdin */
fclose (fp);
}
Input File
With input from the numbers under your "EDIT:", you would have:
$ cat dat/setsofsix.txt
3
3
3
19
16
8
9
15
1
14
12
13
1
7
8
9
6
6
5
Example Use/Output
The program takes the filename to read as the first argument to the program:
$ ./bin/readsetsofsix dat/setsofsix.txt
Set 1
[3, 3, 19] = 25
[16, 8, 9] = 33
Set 2
[15, 1, 14] = 30
[12, 13, 1] = 26
Set 3
[7, 8, 9] = 24
[6, 6, 5] = 17
Let me know if I understood your problem and whether you have further questions. I'm more than happy to help further.
I have the following text file
0 0 0 debut
1 120 0 permis exploitation
2 180 1 1 piste 6km
3 3 1 2 installation sondeuses
4 30 1 2 batiments provisoires
5 60 1 2 groudronnage piste
6 90 1 4 adduction eau
7 240 2 3 4 campagne sondage
8 180 3 5 6 7 forage 3 puits
9 240 3 5 6 7 construction bureaux logements
10 30 2 8 9 transport installation matériel
11 360 2 8 9 traçage du fond
12 240 2 8 9 construction laverie
13 0 3 10 11 12 fin des travaux
Each line is the representation of a task and is described as followed: the first number is and ID, the second is the duration, the third is the number of previous tasks that are required, and all the numbers afterward are the IDs of the required tasks. Finaly the string in the end is the title of the string.
I'm trying to fill an array of those struct by reading this file. Here is the struct:
typedef struct{
int id;
int duration;
int nbPrev; /* number of required previous tasks */
int prev[NMAXPREV]; /*array of required previous tasks*/
char title[LGMAX];
}Task ;
Here is my code to read the file
int readTasksFile(char* file_name, Task t[])
{
FILE* f;
char line[256] = {'\0'};
int i = 0;
char c[1] = {0};
if((f = fopen(file_name, "r")) == NULL)
{
perror("The file couldn't be opened");
exit(EXIT_FAILURE);
}
while (fgets(line, 256, f) != EOF)
{
sscanf_s(line, "&d &d &d", &(t[i].id), &(t[i].duration), &(t[i].nbPrev));
i++;
}
fclose(f);
return 0;
}
How can I read all the previous tasks number in a line considering it is variable and still be able to read the title afterward ?
How can I read all the previous tasks number in a line considering it is variable and still be able to read the title afterward ?
The 3rd int should be the number of following ints.
Use "%n" to record scan offset.
After reading the .prev[], copy the rest of the line to .title.
Add error checking. This is very important, especially for complex input.
// Untested code to get OP started
// while (fgets(line, 256, f) != EOF) Comparing against EOF is incorrect
while (fgets(line, sizeof line, f)) {
int offset = 0;
// Use %d, not &d
if (sscanf(line, "%d %d %d %n",
&t[i].id, &t[i].duration, &t[i].nbPrev, &offset) != 3) {
// Handle bad input, for now, exit loop
break;
}
if (t[i].nbPrev < 0 || t[i].nbPrev > NMAXPREV) {
// Handle bad input, for now, exit loop
break;
}
char *p = line + offset;
int prev;
// Populate t[i].prev[]
for (prev = 0; prev < t[i].nbPrev; prev++) {
if (sscanf(p, "%d %n", &t[i].prev[prev], &offset) != 1) {
break;
}
p += offset;
}
if (prev != t[i].nbPrev) {
// Handle bad input, for now, exit loop
break;
}
// remaining text
int len = strlen(p);
if (len > 0 && p[len-1] == '\n') p[--len] = '\0'; // consume potential trailing \n
if (len >= LGMAX) {
// Handle bad input, for now, exit loop
break;
}
strcpy(t[i].title, p);
i++;
}
return i; // Let caller know of successful lines parsed.
Advanced: robust code would use strtol() instead of "%d" and sscanf().
readTasksFile() should also pass in the max number of Task t[] that can be read.
You could also scan by line and assign the two first numbers to id and duration, then do an int analysis and add the rest of the elements to nbPrev until you encounter a letter.
I don't know if this would be the best way to do it, but it's how I would do it.
Why don't you create also a list each time you register in struct nbPrev?
Like, instead of nbPrev being of type int, make it of type list?
Problem: Write a program that reads all integers that are in the range
of 0 to 100, inclusive from an input file named: a.txt and counts how
many occurrences of each are in the file. After all input has been
processed, display all the values with the number of occurrences that
were in are in the input file.
Note: The program ignores any number less than 0 or greater than 100.
Note: Do not display zero if a number is not in the file. Hints: An
array of size 101 is good enough. A number in the file plays the role
of an index.
For example: Suppose the content of the file: a.txt is as follows:
99 2 99
3
-12 80 12 33
3 99 100 1234 84
The display output is:
2 has occurred: 1 times,
3 has occurred: 2 times,
12 has occurred: 1 times,
33 has occurred: 1 times,
80 has occurred: 1 times,
84 has occurred: 1 times,
99 has occurred: 3 times,
100 has occurred: 1 times
Here is the code that I have right now:
#include <stdio.h>
#include <stdlib.h>
int main(){
FILE *inFile;
int count = 1, num[101];
inFile = fopen("a.txt", "r");
for(int i = 1; i <= 100; i++) {
fscanf(inFile, "%d", &num[i]);
}
for(int i = 1; i <= 100; i++){
if(num[i] == i) {
printf("%i has occurred: %d times\n", i, count);
count++;
}
}
fclose(inFile);
}
Output:
2 has occured: 1 times
Hello, I'm trying to do this assignment for my C Programming class due Sunday at midnight, but I'm having trouble trying to print all of the numbers from the array with their occurrences. In my code, I first declared int count to increase the number of occurrences if the number is found more than once in the text file and created an array size of 101. Then, I used a for loop to read the text file and store all the numbers from 1-100 into the array. The second for loop, followed by an if statement is to compare the numbers from the array. Even though this is a test program, we are supposed to be able to do this with all data values. Hope this is a good enough explanation, thank you.
You are close.
Instead of reading each value into num, You want to use your num array to keep the count of each number seen in the file.
int main() {
FILE* inFile;
int value = 0;
int result = 0;
int num[101] = { 0 }; // zero-init this array
inFile = fopen("a.txt", "r");
if (inFile == NULL) {
printf("unable to open file\n");
return -1;
}
result = fscanf(inFile, "%d", &value);
while (result == 1) {
printf("Just read: %d\n", value);
if ((value >= 0) && (value <= 100)) {
num[value] = num[value] + 1; // num[value]++
}
result = fscanf(inFile, "%d", &value);
}
for (int i = 0; i <= 100; i++) {
if (num[i] > 0) {
printf("%i has occurred: %d times\n", i, num[i]);
}
}
fclose(inFile);
}
In addition to the good answer by #selbie, from my answer to your earlier question How do I get the counter to work..., you can apply the same principals to filling a Frequency Array here. In this case you simply use n as an index instead of a counter.
For example with your index n and your array num declared (and initialized all zero), you would simply read all integers in the file and check if the value n was between 0 <= n <= 100 and if so , update the value at the index n in your num array by one, e.g. num[n]++;. You could do it like:
int n = 0; /* index */
int num[NELEM] = {0}; /* array */
...
while (fscanf(myFile, "%d", &n) == 1) /* read each int */
if (0 <= n && n <= 100) /* if 0 <= n <= 100 */
num[n]++; /* increment value at index */
Then for your output, you just handle your special check on num[0] to determine whether to output that index, and then loop from 1-NELEM outputting the frequency of occurrence of each value, e.g.
if (num[0]) /* check if 0 found, output if so */
printf ("num[%3d] occurred %3d times\n", 0, num[0]);
for (int i = 1; i < NELEM; i++) /* output counts for 1-100 */
printf ("num[%3d] occurred %3d times\n", i, num[i]);
The complete example could be:
#include <stdio.h>
#define NELEM 101 /* if you need a constant, #define one (or more) */
int main(int argc, char **argv) {
int n = 0; /* index */
int num[NELEM] = {0}; /* array */
/* read filename from 1st argument (stdin by default) */
FILE *myFile = argc > 1 ? fopen (argv[1], "r") : stdin;
if (!myFile) { /* validate myfile is open for reading */
perror ("fopen-myfile");
return 1;
}
while (fscanf(myFile, "%d", &n) == 1) /* read each int */
if (0 <= n && n <= 100) /* if 0 <= n <= 100 */
num[n]++; /* increment value at index */
if (myFile != stdin) /* close file if not stdin */
fclose (myFile);
if (num[0]) /* check if 0 found, output if so */
printf ("num[%3d] occurred %3d times\n", 0, num[0]);
for (int i = 1; i < NELEM; i++) /* output counts for 1-100 */
printf ("num[%3d] occurred %3d times\n", i, num[i]);
}
Example Use/Output
With 500 random integers in a file, you would get output similar to:
$ ./bin/fscanffreq dat/500_rand_0-100.txt
num[ 0] occurred 3 times
num[ 1] occurred 8 times
num[ 2] occurred 7 times
num[ 3] occurred 2 times
num[ 4] occurred 1 times
num[ 5] occurred 4 times
num[ 6] occurred 3 times
num[ 7] occurred 5 times
num[ 8] occurred 6 times
num[ 9] occurred 4 times
num[ 10] occurred 6 times
...
num[ 95] occurred 6 times
num[ 96] occurred 4 times
num[ 97] occurred 6 times
num[ 98] occurred 2 times
num[ 99] occurred 5 times
num[100] occurred 6 times
(note: if num[0] was 0, it would not be displayed)
Look things over and let me know if you have further questions.
It's my first try in writing into a file with c.
The part making the problem is the following:
for (j = 0; j < num_probs; j++) {
fprintf(dataMy, "%i ", data_my[j]);
}
Additional information: data_my is an int array filled just with 0 and 1 (a lot of them)
If the code is executed there are just these symbols
‰‰‰‰‱‱‱‱‱‱‱
instead of
0 0 0 0 1 1 1 1 1 1 1
in my .txt file.
If I change %i in fprintf(dataMy, "%i ", data_my[j]) to %2i which gives 2 characters each time printed, but because I use only 0 or 1 (1 character each), one is a spacebar. Or I can write %i which works too, but I want to start my .txt file without a spacebar.
Here is my complete program:
#include <stdio.h>
#include <stdlib.h>
#include <Windows.h>
#define num_annos 523
#define num_probs 1910
#define meine_zeile 59
int data[num_annos][num_probs];
void main() {
int i, j;
FILE *f = NULL;
FILE *dataMy = NULL;
errno_t err;
int data_my[num_probs];
if ((err = fopen_s(&f, "H:\\Hochschule\\Informatik\\UebungenIII\\Daten für A6_15WS_all\\datamatrix_v5_1.txt", "r")) != 0) {
printf("The file was not opened\n");
} else {
printf("Datei erfolgreich geoeffnet!\n\n");
for (i = 0; i < num_annos; i++) {
for (j = 0; j < num_probs; j++) {
fscanf_s(f, "%i", &data[i][j]);
printf("%2i", data[i][j]);
}
printf("\n");
}
fclose(f);
printf("\n\nEinlesen erfolgreich.\n");
}
for (j = 0; j < num_probs; j++) {
data_my[j] = data[meine_zeile-1][j];
}
if ((err = fopen_s(&dataMy, "H:\\Hochschule\\Informatik\\UebungenIII\\Daten für A6_15WS_all\\data_my.txt", "w")) != 0) {
printf("The file was not opened\n");
} else {
for (j = 0; j < num_probs; j++) {
fprintf(dataMy, "%i ", data_my[j]);
printf("%i ", data_my[j]);
}
fclose(dataMy);
}
getch();
}
It reads in 0 and 1 from the datamatrix_v5_1.txt (this file is just filled with 0 1 1 0 1 0 1 0 1... and so on), saves one of these lines into the array data_my and thats what I want to print into the data_my.txt.
The characters ‰ and ‱ have the Unicode code-points 0x2030 and 0x2031 respectively. Encoded as UTF-16 and then interpreted as ASCII, these are ' 0' and ' 1' or '0 ' and '1 ', depending on byte-order. It seems like your ASCII output is somehow interpreted as if it was UTF-16.
This can happen if you perform byte-wise output on a wide-character stream. This can also happen because your editor's encoding-detection routine malfunctioned (cf. Bush hid the facts). Try to manually set a text encoding when editing the file or use ea different editor.
I'm trying to extract the content of a file into a matrix but the file may look completely differently.
For exemple all these files should give the same result : a 3x3 matrix containing 1,2,3,4,5,6,7,8,9.
1 2 3
4 5 6
7 8 9
1 2 3
4 5 6
7 8 9
1 2 3 4
5
6
7 8
9
1 2 3
$something
$something else
4 5 6
$something else else
7 8 9
Hopefully I know the dimensions of the matrix beforehand as well as the "$" character that indicates that these lines are to be ignored in the current process.
My current algorithm using fscanf works great but It can't work with the "$something" lines.
I figured that I should use the fgets/strtok/sscanf method but there are some issues.
// File* file (already assigned)
char line[32]; //assuming 32 is enough
char* token;
fgets(line,32,file);
token = strtok(line," \t");
for (y=0; y<ySize; y++)
{
for (x=0; x<xSize, x++)
{
if (token[0] == '$') //should use a str function
{
fgets(line,32,file);
token = strtok(line," \t")
x--;
}
else
{
if (we are at the end of the line)
{
fgets(line,32,file);
token = strtok(line," \t")
}
sscanf(token,"%d",&matrix[x][y];
token = strtok(NULL," \t");
}
}
}
Basically I'd like to have some help to write the "if (we are at the end of the line)" condition and some input on my method, is it flawless? Did I correctly thought of the process?
Thank you.
You should use getline instead of fgets to make things easier. The latter is unreliable. The test condition that you are looking for is:
token == NULL;
Check this: "Once the terminating null character of str has been found in a call to strtok, all subsequent calls to this function with a null pointer as the first argument return a null pointer."
You can easily parse without strtok() by using strspn() / strcspn(), and sscanf()s "%n" specifier. Also: there was a ',' in the original code where a ';' should have been.
#include <stdio.h>
#include <string.h>
#define XSIZE 3
#define YSIZE 3
int matrix[XSIZE][YSIZE];
int main(void)
{
char line[200];
int pos,eat,xx,yy, rc;
xx = yy =0;
while ( fgets(line, sizeof line, stdin) ) {
if (line[0] == '$') continue;
for(pos=0; line[pos]; pos += eat) {
pos += strspn(line+pos, " \t\n");
rc =sscanf(line+pos, "%d%n", &matrix[xx][yy], &eat);
if (rc < 1) break;
if (++xx >= XSIZE ) {xx = 0; if(++yy >= YSIZE) goto done; }
}
}
done:
/* show it to the world ... */
for (yy = 0; yy < YSIZE; yy++) {
for (xx = 0; xx < XSIZE; xx++) {
fprintf (stdout, " %d", matrix[xx][yy] );
}
fprintf (stdout, "\n" );
}
return 0;
}