I have a file like this
GET /index.html k
GET /docencia.html k
GET /ejemplo.html k
and I want to read it line by line and split it up with this delimiter " " but is giving me this error: segmentation fault(core dumped) and I don't know what to try.
This is my code:
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[]) {
char ordenes[150];
char *orden[3];
char *token;
int tok;
FILE *fp;
fp = fopen(argv[1], "r");
if (fp == NULL) {
printf("File error");
exit(1);
}
while (feof(fp) == 0) {
fgets(ordenes, sizeof(ordenes), fp);
printf("%s \n", ordenes);
token = strtok(ordenes, " ");
tok = 0;
while (token != NULL) {
orden[tok] = strdup(token);
tok++;
token = strtok(NULL, " ");
}
printf("\n%s\n", orden[0]);
printf("\n%s\n", orden[1]);
printf("\n%s\n", orden[2]);
}
fclose(fp);
}
The error shows when I call the first strdup. If I try to print the token just after I call the first strtok, it fails too (the same segmentation fault core dumped) so I guess the problem is with the strtok.
You do not include <string.h>, so the compiler applies the default argument promotions on the signature of strtok, in particular it considers that strtok returns an int.
So the compiler will apply an operator of coercion from int to pointer to char at the assignment
token = strtok(ordenes, " ");
and this assignment will be compiled as
token = (int->char*) strtok(ordenes, " ");
There are multiple problems in your code:
As alinsoar diagnosed with a sharp eye, you do not include <string.h>. strtok is not defined, the compiler must assume it returns an int, which it does not, and this int is silently converted to a char *. The code generated invokes undefined behavior and will most likely crash on 64-bit targets. You should compile with all warnings enabled to let the compiler help avoid this kind of silly mistake. gcc -Wall -W or clang -Weverything...
You do not check if command line arguments have been passed to your program before calling fp = fopen(argv[1], "r");. If no arguments are passed, argv[1] is a null pointer.
while (feof(fp) == 0) is incorrect, read Why is “while ( !feof (file) )” always wrong? . You should instead write while (fgets(ordenes, sizeof(ordenes), fp)) {...
You do not check if tok < 3 before storing token into the orden array. If the line has more than 3 fields, you will cause a buffer overflow.
You do not check if 3 tokens were indeed found before printing all 3 entries in orden. This too might invoke undefined behavior, especially if fgets() failed to read a line, which you do not check.
Here is an improved version:
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char *argv[]) {
char ordenes[150];
char *orden[3];
char *token;
int i, tok;
if (argc < 2) {
fprintf(stderr, "Missing command line argument\n");
exit(1);
}
FILE *fp = fopen(argv[1], "r");
if (fp == NULL) {
fprintf(stderr, "Cannot open input file %s: %s\n",
argv[1], strerror(errno));
exit(1);
}
while (fgets(ordenes, sizeof(ordenes), fp)) {
printf("%s", ordenes);
token = strtok(ordenes, " ");
for (tok = 0; tok < 3 && token != NULL; tok++) {
orden[tok] = strdup(token);
token = strtok(NULL, " ");
}
for (i = 0; i < tok; i++) {
printf("%s\n", orden[i]);
free(orden[i]);
}
printf("\n");
}
fclose(fp);
return 0;
}
For starters you should change the condition in the outer loop statement the following way
while ( fgets(ordenes, sizeof(ordenes), fp) != NULL )
The condition in the inner loop should be written at least like
while ( tok < 3 && token != NULL) {
The tokens should be outputted in a loop and the allocated memory must be freed. For example
for ( int i = 0; i < tok; i++ )
{
printf("\n%s\n", orden[i]);
free( orden[i]);
}
You can do the following:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
static void play_with_token(char *token, char const *delim)
{
if (token == NULL)
return;
printf(" %s", token);
play_with_token(strtok(NULL, delim), delim);
}
int main(int argc, char *argv[])
{
if (argc != 2)
return 1;
FILE *fp = fopen(argv[1], "r");
if (fp == NULL)
return 1;
char *line = NULL;
size_t len = 0;
ssize_t read;
while ((read = getline(&line, &len, fp)) != -1) {
printf("parsing line :");
char const *delim = " ";
play_with_token(strtok(line, delim), delim);
printf("\n");
}
free(line);
fclose(fp);
}
try this:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char *argv[]){
char ordenes[150];
char *orden[3];
char *token;
int tok;
FILE *fp;
fp = fopen (argv[1], "r");
if(fp==NULL){
printf("File error");
exit(1);
}
while(fgets(ordenes, sizeof(ordenes), fp)){
printf("%s\n",ordenes);
token = strtok(ordenes, " ");
tok = 0;
while (token != NULL){
orden[tok++] = strdup(token);
token = strtok(NULL," ");
}
printf("\n%s\n",orden[0]);
printf("\n%s\n",orden[1]);
printf("\n%s\n",orden[2]);
free(orden[0]);free(orden[1]);free(orden[2]);
}
fclose(fp);
}
Related
The idea of this function is to get strings from file like this:
The file CLIENTS_BOOK: client1,client2,client3
and to get this in array of strings, eg:
CLIENTS_BOOK_ARRAY[i] to be equal to "client1"
CLIENTS_BOOK_ARRAY[i+1] to be equal to "client2"
CLIENTS_BOOK_ARRAY[i+2] to be equal to "client3"
Here is the code:
//global array
static char CLIENTS_BOOK_ARRAY[MAX_SIZE_OF_ARRAYS][MAX_SIZE_OF_ARRAYS];
void get_clients_string() {
int i = 0;
int n = 0;
char *token;
char help[256];
FILE *InputFile;
InputFile = fopen(CLIENTS_BOOK, "r");
fscanf(InputFile, "%s", help);
token = strtok(help, ",");
while (token != NULL) {
strncpy(CLIENTS_BOOK_ARRAY[i], token, MAX_SIZE_OF_ARRAYS);
token = strtok(NULL, ",");
i++;
}
n = i;
fclose(InputFile);
}
When I run it, it is giving
Segmentation fault(core dumped)
When running it with gdb it is giving
Program received signal SIGSEGV, Segmentation fault.
0x00007ffff7f2ce38 in __strncpy_avx2_rtm () from /usr/lib/libc.so.6
The interesting part comes when it is running as intended on my pc (Arch linux, amd cpu), and it does not on my laptop (Arch linux, intel cpu).
There are multiple problems in your code:
you do not test the return value of fopen(). If the file cannot be open, InputFile will be a null pointer and fscanf() will have undefined behavior.
fscanf(InputFile, "%s", help); will write beyond the end of the help array if the word in the file has 256 bytes or more. Use this instead:
fscanf(InputFile, "%255s", help);
or possibly:
fgets(help, sizeof help, InputFile);
and test for failure to read the file contents.
strncpy is not your friend: strncpy(CLIENTS_BOOK_ARRAY[i], token, MAX_SIZE_OF_ARRAYS) will not null terminate the string if it happens to be longer than MAX_SIZE_OF_ARRAYS - 1 bytes. Do not use strncpy, use strncat, snprintf or strlcpy if available instead.
the loop does not stop at the end of the 2D array: you should check that i < MAX_SIZE_OF_ARRAYS in the while test.
Here is a modified version:
#include <stdio.h>
#include <string.h>
#define CLIENT_SIZE 100
#define CLIENT_NUMBER 100
#define CLIENTS_BOOK "client_book.txt"
static char client_book[CLIENT_NUMBER][CLIENT_SIZE];
int get_clients_string(void) {
int n = 0;
char buf[256];
FILE *InputFile = fopen(CLIENTS_BOOK, "r");
if (InputFile == NULL) {
fprintf(stderr, "error opening %s: %s\n",
CLIENTS_BOOK, strerror(errno));
return -1;
}
if (fgets(buf, sizeof buf, InputFile)) {
char *token = strtok(help, ",\n");
while (n < CLIENT_NUMBER && token != NULL) {
client_book[n][0] = '\0';
strncat(client_book[n], token, CLIENT_SIZE - 1);
token = strtok(NULL, ",");
n++;
}
} else {
fprintf(stderr, "%s: no clients\n", CLIENTS_BOOK);
}
fclose(InputFile);
return n;
}
I want to put each of this words in a array.
And here is the code.
And here is the output
From what i can understand each time i have a new line the first word of the array is replaced by the fisrt word of the next line of the file, but i dont understand why.
I ditnt show here but after the new line all the other positions are all wrong.
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <assert.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#define MAX_LINE_LEN 256
void usage (const char *prog) {
fprintf (stderr, "Usage (words): %s [file_path]\n", prog);
exit (1);
}
void split_print_words (const char *filename) {
FILE *fd = stdin; // By default will read from stdin
if (filename != NULL && strcmp (filename, "-") != 0) {
// A file name was given, let's open it to read from there
fd = fopen (filename, "r");
assert (fd != NULL);
}
char buffer[MAX_LINE_LEN];
while(fgets(buffer, sizeof(buffer), fd != NULL)) {
char *token;
token = strtok(buffer, " \n");
while(token!=NULL) {
write(1, token, strlen(token));
write(1, "\n", 1);
token = strtok(NULL, " \n");
}
}
}
int main (int argc, char *argv[]) {
// Check there is one and only one argument
if (argc < 1 || argc > 2) {
usage (argv[0]);
}
split_print_words (argv[1]);
exit (0);
}
Try this (read the comments):
#include <stdio.h>
#include <string.h>
#define MAX_LINE_LEN 256
#define WORDS_N 10
int main(void)
{
FILE* fp;
// Open the file and check if it was opened
fp = fopen("myfile.txt", "r");
if (fp == NULL) {
perror("Failed: ");
return 1;
}
// Temporary buffer that will store one line of the file at a time
char buffer[MAX_LINE_LEN];
// NULL-initialized 2D array of size 'WORDS_N' x 'MAX_LINE_LEN'
char words[WORDS_N][MAX_LINE_LEN] = {0};
// Count how many words we actually read from the file
int count = 0;
// To be used by 'strtok()'
char* pch;
// Read file line by line
while (fgets(buffer, MAX_LINE_LEN, fp))
{
// Remove trailing newline
buffer[strcspn(buffer, "\n")] = 0;
//printf("%s\n", buffer);
// Split line by whitespace
pch = strtok(buffer, " ");
// For each token in the split line
while (pch != NULL)
{
// If the array has available space
if(count < WORDS_N)
// Put the current token into the array
strcpy(words[count++], pch);
//printf ("%s\n", pch);
// Proceed to next token
pch = strtok(NULL, " ");
}
}
// Print array
for (int i = 0; i < count; ++i)
printf("%s\n", words[i]);
// Close file
fclose(fp);
return 0;
}
Input (myfile.txt):
This is a
test and is
not working!
Output:
This
is
a
test
and
is
not
working!
As pointed out in the comments, You should replace this:
while(fgets(buffer, sizeof(buffer), fd != NULL)) {
with this:
while((fgets(buffer, sizeof(buffer), fd)) != NULL) {
I'm not sure how you've set up your compiler. I clearly got a warning from gcc when I compiled your code:
arrayreplace.c: In function ‘split_print_words’:
arrayreplace.c:27:48: warning: passing argument 3 of ‘fgets’ makes pointer from integer without a cast [-Wint-conversion]
27 | while(fgets(buffer, sizeof(buffer), fd != NULL)) {
| ^
| |
| int
In file included from arrayreplace.c:3:
/usr/include/stdio.h:564:69: note: expected ‘FILE * restrict’ but argument is of type ‘int’
564 | extern char *fgets (char *__restrict __s, int __n, FILE *__restrict __stream)
| ~~~~~~~~~~~~~~~~~^~~~~~~~
After making this change, I was able to see all words being parsed from file:
src : $ cat wordsarr.txt
This ia a
test and is
not working
src : $ ./a.out wordsarr.txt
This
ia
a
test
and
is
not
working
I'm trying to write an Excel archive(input) into an empty archive. The aim is to write a new Excel without the dates, but when I try, the new archive is erasing some lines in the excel and not erasing the dates as I wanted to. Is it something with the code?
Input
1760
02/20/18,11403.7
02/19/18,11225.3
02/18/18,10551.8
02/17/18,11112.7
02/16/18,10233.9
02/15/18,10166.4
02/14/18,9494.63
02/13/18,8598.31
Actual Output
1760
02/20/18
11403.7
02/19/18
11225.3
02/18/18
10551.8
02/17/18
11112.7
02/16/18
10233.9
02/15/18
10166.4
02/14/18
9494.63
02/13/18
8598.31
Expected Output
1760
11403.7
11225.3
10551.8
11112.7
10233.9
10166.4
9494.63
8598.31
This is my code:
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
int main(int argc,char **argv){
FILE *btc;
FILE *out;
if((out = fopen("new.csv", "w")) == NULL ){
printf("not found new\n");
exit(1);
}
if((btc = fopen("BTC.csv", "r")) == NULL ){
printf("not found btc\n");
exit(1);
}
long int a;
char linha[256];
char *token = NULL;
while (!feof(btc))
{
fgets(linha, 256, btc);
token = strtok(linha, ",\n");
while ((token != NULL) && (!feof(btc)))
{
a++;
fprintf(out, "%s\n", token);
token = strtok(NULL, " \n");
}
}
fclose(btc);
fclose(out);
return 0;
}
As far as I can see, you want to drop the date field, which is the first field. You need to arrange not to print the first token found by strtok() on each line — except the first where you should probably print 1760 by not scanning the 1 as a separate operation.
That leads to code like this:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void)
{
const char *name1 = "BTC.csv";
const char *name2 = "new.csv";
FILE *out;
FILE *btc;
if ((btc = fopen(name1, "r")) == NULL)
{
fprintf(stderr, "failed to open file %s for reading\n", name1);
exit(1);
}
if ((out = fopen(name2, "w")) == NULL)
{
fprintf(stderr, "failed to open file %s for writing\n", name2);
exit(1);
}
int lineno = 0;
char linha[256];
char *token = NULL;
while (fgets(linha, sizeof(linha), btc) != 0)
{
if (++lineno == 1)
fprintf(out, "%s", linha);
else
{
token = strtok(linha, ",\n");
if (token == NULL)
break;
while ((token = strtok(NULL, ",\n")) != 0)
fprintf(out, "%s\n", token);
}
}
fclose(btc);
fclose(out);
return 0;
}
Given input file BTC.csv:
1760
02/20/18,11403.7
02/19/18,11225.3
02/18/18,10551.8
02/17/18,11112.7
02/16/18,10233.9
02/15/18,10166.4
02/14/18,9494.63
02/13/18,8598.31
the program creates output file new.csv:
1760
11403.7
11225.3
10551.8
11112.7
10233.9
10166.4
9494.63
8598.31
This seems to correspond to what is wanted.
I was just creating simple implementation where I read input.txt file which has one line of code containing two numbers separated by space (e.g. 4 4).
I was trying to separate them by delimiting with space first.
And I was trying to use the first value as a size of char array.
However it keeps causing segmentation fault but I have no idea.
int main(int argc, char **argv){
int number;
int i = 0;
char *token;
char buf[100];
int tempNum[2];
// Open file
FILE * fPointer;
fPointer = fopen("input.txt", "r");
// Read first line
fgets(buf, 1024, fPointer);
token = strtok(buf, " ");
number = atoi(token);
char charArray[number];
while(token != NULL){
tempNum[i] = atoi(token);
token = strtok(NULL, "\n");
printf("%d\n", tempNum[i]);
i++;
}
If I comment out "char charArray[number]" it does not cause segmentation fault. If I comment out only the while loop, it does not cause segmentation fault. But I cannot figure out why it is causing the segmentation in the first place. Please help.
Thank you in advance.
Something like this?
#include <stdlib.h>
#include <stdio.h>
#include <stdio.h>
#include <string.h>
#define BUF_SIZE 1024
#define MAX_INPUT 2
int main(int argc, char **argv) {
char *token = NULL;
char *next_token = NULL;
char buf[BUF_SIZE];
long tempNum[MAX_INPUT] = { 0 };
const char *delim = " ";
char * end = NULL;
// Init vars
memset(buf, 0, BUF_SIZE);
// Open file
FILE * fPointer = fopen("input.txt", "r");
if (fPointer == NULL) {
return 1;
}
// Read first line
if (fgets(buf, BUF_SIZE, fPointer) == NULL) {
fclose(fPointer);
return 2;
}
// Parse line
token = strtok_s(buf, delim, &next_token);
for (int i = 0;((i < MAX_INPUT) && (token != NULL)); i++){
tempNum[i] = strtol(token, &end, 10);
if (*end != NULL){
printf("error in %s\n", token);
} else {
printf("%d\n", tempNum[i]);
}
token = strtok_s(NULL, delim, &next_token);
}
fclose(fPointer);
return 0;
}
I'm trying to read in a file with a couple hundred integers, some positive, some negative and store them in an array. They have to be read in as a string using strtok, though. I keep getting a segmentation fault and I'm not sure why. The count is to figure out how many total integers are in the file.
/*Input file looks like this:
718321747 -1828022042
-1665405912 -175307986
-53757018 -1551069786 525902369
-1945908378 853648883
*/
int main(int argc, char* argv[])
{
char buffer[50];
char* token;
int count = 0;
int num = 0;
int arr[MAX_SIZE];
if (argc != 2)
{
printf("Invalid number of arguments\n");
return 0;
}
FILE* fptr = fopen(argv[1], "r");
//open file
if (fptr == NULL)
{
printf("Unable to open file\n");
return 0;
}
while(fgets(buffer, 50, fptr))
//to get the file line by line
{
token = strtok(buffer, "\n\t ");
//find first token
num = atoi(token);
//convert it to an int
arr[count] = num;
//store in array
count++;
while(token != NULL)
//get rest of tokens and convert to int
{
token = strtok(buffer, "\n\t ");
num = atoi(token);
arr[count] = num;
count++;
}
}
return 0;
}
You never check if the token was found in the string, you must check that strtok() didn't return NULL before trying to call atoi().
Then you keep scanning the same string with strtok() passing the string in each iteration, that's also wrong, you should pass NULL after the first time.
I would also recommend to use strtol() instead of atoi() to check if the conversion was successful.
Check this code, i fixed it
#include <stdio.h>
#include <stdlib.h>
#define MAX_SIZE 1000 /* ? whatever value you think is good. */
int main(int argc, char* argv[])
{
char buffer[50];
int count = 0;
int arr[MAX_SIZE];
if (argc != 2)
{
printf("Invalid number of arguments\n");
return 0;
}
FILE* fptr = fopen(argv[1], "r");
//open file
if (fptr == NULL)
{
printf("Unable to open file\n");
return 0;
}
//to get the file line by line
while ((fgets(buffer, 50, fptr) != NULL) && (count < MAX_SIZE))
{
char *pointer;
char *token;
pointer = buffer;
while (((token = strtok(pointer, "\n\t ")) != NULL) && (count < MAX_SIZE))
{
char *endptr;
arr[count] = strtol(token, &endptr, 10);
printf("%d\n", arr[count]);
if (*endptr != '\0')
printf("error: could not convert %s to integer\n", token);
else
count++;
pointer = NULL;
}
}
return 0;
}
I am not sure it will work for you because I haven't seen the structure of your input data, but I am sure it will not cause a segmentation fault.