Reputation: 115
I have a text file that reads as follows:
5f6
2f6
4f6
I'd like to obtain the numbers from that textfile (as chars then convert them to integers using atol()
I have the code:
#include <ncurses.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
int main(int argc, char * argv[])
{
initscr();
cbreak();
noecho();
char buf[100];
char * ptr;
char * ptr2;
char * ptr3;
char * ptr4;
int a;
int b;
int c;
int d;
FILE* file;
if (strcmp(argv[1],"test.txt") == 0)
{
file = fopen("test.txt","r");
while (fgets(buf,100,file) )
ptr = strtok(str,"f");
ptr2 = strtok(NULL," ");
ptr3 = strtok(NULL,"f");
ptr4 = strtok(NULL," ");
a = atol(ptr);
b = atol(ptr2);
c = atol(ptr3);
d = atol(ptr4);
}
refresh();
getchar();
endwin();
return (0);
}
however, the program seg faults but compiles. How would I go about doing this more efficiently (By a method that doesn't seg fault)?
Upvotes: 0
Views: 98
Reputation: 409422
If, for example, you want to get the digits from e.g.
5f6
as numbers, that's much more easy than you think. Just read the first and the third character, and convert them to numbers using simple arithmetic.
Example:
char line[8];
while (fgets(line, sizeof line, file) != NULL)
{
int firstDigit = line[0] - '0';
int secondDigit = line[2] - '0';
printf("%d %d\n", firstDigit, secondDigit);
}
For the example input you show
5f6 2f6 4f6
the output will be
5 6 2 6 4 6
If you're wondering about the arithmetic, it works because most character encodings (like the most common ASCII) keeps the digit characters in a consecutive range. In the example of ASCII, the value for e.g. '5'
is 53
, and the value for '0'
is 48
. That means the subtraction of '5' - '0'
results in 53 - 48
which is equal to 5
.
Upvotes: 1
Reputation: 53016
You have several problems
You don't check if the file opened.
After fopen()
you must ensure that you can read from the file, if fopen()
fails, it returns NULL
so a simple
if (file == NULL)
return -1;
would prevent problems in the rest of the program.
Your while
loop only contains one statement because it lacks braces.
Without the braces your while loop is equivalent to
while (fgets(buf, sizeof(buf), file))
{
ptr = strtok(buf, "f");
}
You don't check that strtok()
returned a non NULL
value.
If the token is not found in the string, strtok()
returns NULL
, and you passed the returned pointers to atol
anyway.
That would cause undefined behavior, and perhaps a segementation fault.
You don't check if there was an argument passed to the program but you still try to compare it to a string. Also potential undefined behavior.
I don't know if the following program will do what you need since it's your own program, I just made it safer, avoided undefined behavior
#include <ncurses.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
int main(int argc, char * argv[])
{
char buf[100];
char *ptr;
char *ptr2;
char *ptr3;
char *ptr4;
int a;
int b;
int c;
int d;
FILE *file;
initscr();
cbreak();
noecho();
if (argc > 1)
{
file = fopen(argv[1], "r");
if (file == NULL)
return -1;
while (fgets(buf,100,file) != NULL)
{
ptr = strtok(str,"f");
ptr2 = strtok(NULL," ");
ptr3 = strtok(NULL,"f");
ptr4 = strtok(NULL," ");
if (ptr != NULL)
a = atoi(ptr);
if (ptr2 != NULL)
b = atoi(ptr2);
if (ptr3 != NULL)
c = atoi(ptr3);
if (ptr4 != NULL)
d = atoi(ptr4);
}
}
refresh();
getchar();
endwin();
return 0;
}
Upvotes: 2