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;
}
Related
#include <stdio.h>
#include <string.h>
int main()
{
//read any text file
char const* const fName = "database-large.txt";
FILE* fp = fopen(fName, "r");
char *ptr;
char substr[5000];
long i=0, j=0;
// if file not opened
if(!fp){
printf("\n Error in open : %s ", fName);
return -1;
}
// to strore each line
char line[5000];
// read line by line
while (fgets(line, sizeof(line), fp)) {
//to extract mailid in between "From:" and "\n"
ptr = strstr(line, "Date:");
i=ptr-line;
while(line[i] !='\n')
{
substr[j] = line[i+9];
i++;
j++;
}
printf("%s\n", substr);
}
// to close the file
fclose(fp);
return 0;
}
Why does this compile but gives me a segmentation fault when when I run it because of the line "while(line[i] !='\n')".This is the only issue I have when running my code.
You need to check whether strstr returned a null pointer or not. Otherwise the following statement after the call of strstr
ptr = strstr(line, "Date:");
i=ptr-line;
can invoke undefined behavior when ptr is equal to NULL.
The second problem is that you do not reset the variable j to 0 in each iteration of the while loop.
And the third problem is that the array substr has to contain a string if you are using the conversion specifier %s in this call
printf("%s\n", substr);
Otherwise you need to write
printf("%.*s\n", ( int )j, substr);
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;
}
Hello and good evening,
So i'm writing a program in C, that will accept a file.txt as an input and read the text. The program should read the text file, find the longest and shortest word within the file, and print them out when it reaches the end.
I'm REALLY close but i'm getting a seg fault and, not only do I not know why, but i'm at a loss as to how to fix it.
Here's the code:
#include <stdio.h>
#include <string.h>
FILE *fp;
char str[60];
char *largest;
char *smallest;
char *word;
int i, j;
int main (int argc, char **argv) {
// check that there are only two arguments
if (argc == 2) {
fp = fopen(argv[1], "r");
}
// if not throw this error
else {
perror("Argument error.");
return (-1);
}
// check if the file exists
if (fp == NULL) {
perror("Error opening file.");
return (-1);
}
// set largest to first string and smallest to second
largest = strcpy(largest, strtok(str, " "));
smallest = strcpy(smallest, strtok(NULL, " "));
word = strcpy(word, strtok(str, " "));
// while we get lines of the file
while (fgets (str, 60, fp) != NULL) {
// while the token string isn't empty
while (word != NULL) {
if (strlen(largest) > strlen(word)) {
strcpy(word, largest);
}
if (strlen(smallest) < strlen(word)) {
strcpy(word, smallest);
}
}
}
printf("The largest word in the file is: %s", largest);
printf("The smallest word in the file is: %s", smallest);
fclose(fp);
return 0;
}
I'm pretty sure it's the second while loop...I don't want to use it anyway, but i've been hacking at this for so long it's all my logic can think of.
Any help would be appreciated. This IS homework, though only a small part of it, and i'm not asking for helping solving the entire problem.
Also, there is a Makefile involved...I don't think it's important post but feel free to ask me and i'll update.
As I built this I can confirm that the file is able to read and I can print, put, and do all kinds of cool things. It only broke when I tried to implement my logic for longest/shortest word.
Thanks!
There are some problems with your logic. Try the below code
Few assumptions I made are,
Maximum word length is 20 characters. You can change it by MAX_WORD_LENGTH macro.
Words in file are space separated
Max line length is 60 characters
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define MAX_WORD_LENGTH 20
int main (int argc, char **argv)
{
FILE *fp;
char str[60];
char *largest = (char*) malloc (MAX_WORD_LENGTH);
char *smallest = (char*) malloc (MAX_WORD_LENGTH);
int smallest_len = MAX_WORD_LENGTH, largest_len = 0;
if (argc == 2)
{
fp = fopen(argv[1], "r");
}
else
{
printf("Argument error.");
return (-1);
}
if (fp == NULL)
{
printf("Error opening file.");
return (-1);
}
while (fgets (str, 60, fp) != NULL)
{
char *temp = strtok(str, " ");
while (temp != NULL)
{
if (strlen(temp) > largest_len)
{
strcpy(largest, temp);
largest_len = strlen(largest);
}
if (strlen(temp) < smallest_len)
{
strcpy(smallest, temp);
smallest_len = strlen(smallest);
}
temp = strtok(NULL, " ");
}
}
printf("The largest word in the file is: %s\n", largest);
printf("The smallest word in the file is: %s\n", smallest);
fclose(fp);
return 0;
}
Adopt it for your needs with argv[2]
and enjoy
#include <stdio.h>
#include <string.h>
int main() {
const int max_word_length = 60;
char longest[max_word_length];
char shortest[max_word_length];
char current[max_word_length];
size_t longest_length = 0;
size_t shortest_length = max_word_length;
size_t current_length = 0;
freopen("input", "r", stdin);
freopen("output", "w", stdout);
while (scanf("%s", current) > 0) {
current_length = strlen(current);
if ( current_length > longest_length) {
longest_length = current_length;
strcpy(longest, current);
}
if (current_length < shortest_length) {
shortest_length = current_length;
strcpy(shortest, current);
}
}
printf("%s %s", shortest, longest);
return 0;
}
So I just ran this online and it looks like the seg fault is caused by the line
largest = strcpy(largest, strtok(str, " "));
This is because largest is the destination of the string copy in the call
strcpy(largest, strtok(str, " "));
but it's a pointer that points to nothing. It should be declared as an actual array like this:
char largest[60];
Also, you shouldn't be calling strtok on a str when it hasn't been initialized to anything. It's not even a proper string so there's no way strtok is going to do anything useful at that point.
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);
}
My code is not putting the text file data into line on the second pass of the while loop, and any subsequent pass. I'm sure it's a silly error but I cannot find it.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
FILE *fr;
char *line,*word,*vali;
ssize_t read;
int i=0,sum=0,len =0,flag=0;
const char delim[2]=" ";
int main(int argc, char* argv[])
{
line = (char *)malloc(sizeof(&len));
word = (char *)malloc(sizeof(&len));
vali = (char *)malloc(sizeof(&len));
fr = fopen(argv[1], "r");
if(fr==NULL)
{
exit(EXIT_FAILURE);
}
while ((read = getline(&line, &len, fr)) != -1)
{
printf("line is %s\n", line );
fscanf(fr,"%s%*[^\n]",word);
printf("%s ", word);
vali=strtok(line, delim);
while(vali != NULL)
{
sum=sum+atoi(vali);
vali = strtok(NULL, delim);
}
printf("%d\n", sum);
sum=0;
vali=" ";
len = strlen(line);
}
fclose(fr);
if (line)
free(line);
return 0;
}
If len is some integral type containing the desired length of the first line, then:
&len
Has type pointer-to-integer, and
sizeof(&len)
Returns the size of a pointer (8 bytes on most 64 bit systems) and
malloc(sizeof(&len))
Allocates only 8 bytes of memory (or whatever pointer size is on your system).
This is probably at least part of the issue.