I am having trouble with segmentation fault (core dumped) in C. I am compiling using gcc, and I can't seem to fix it! Here is the code, which is supposed to look at a csv file and perform 1 of 4 opperations:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
int main(int argc, const char * argv[])
{
int lines=0, i=0, a=0;
char strings[128], *broken=" ", *array[100][4], *err=" ";
FILE *file;
file=fopen("inventory.csv", "a+");
broken= malloc(1000);
err=malloc(100);
while(fgets(strings, sizeof strings, file)!=NULL){
++lines;
a=0;
broken=strtok(strings, ",");
while(broken!=NULL){
strcpy( array[i][a], broken);
a++;
}
i++;
}
if(strcmp(argv[1], "list")==0){
printf("Name, Quantity, Reorder limit, Cost");
while(fgets(strings, sizeof strings, file)!=NULL){
while(broken!=NULL){
printf("%s, ", array[i][a]);
}
printf("\n");
}
}
else if(strcmp(argv[1], "reorder")==0){
int i=0;
printf("We need to purchase more of the following items: \n");
for(i=0;i<lines;i++){
if(strtod(array[i][1], &err)<=strtod(array[i][2],&err)){
printf("%s\n", array[i][0]);
}
}
}
else if(strcmp(argv[1], "deduct")==0){
if(argv[2]){
int i=0;
char str[100];
for(i=0;i<lines;i++){
if(strcmp(argv[2], array[i][0])==0){
if(strtod(array[i][1],&err)-1>0){
sprintf(str,"%f",strtod(array[i][1],&err)-1);
array[i][1]=str;
printf("Success\n");
fseek(file, 0, 1);
sprintf(str,"%s,%s,%s,%s", array[i][0], array[i][1],
array[i][2], array[i][3]);
fwrite(str,1,sizeof(str),file);
}
else{
printf("There are none left!\n");
}
}
}
}
else{
printf("Enter a food item");
}
}
else if(strcmp(argv[1], "add")==0){
fseek(file, 0, 2);
char str[100];
sprintf(str,"%s,%s,%s,%s\n",argv[2],argv[3],argv[4],argv[5]);
fwrite(str,1,sizeof(str),file);
}
else{
printf("Please enter an argument: list, reorder, deduct _name_, add _name_
_qty_ _reorderlimit_ _price_\n");
}
fclose(file);
return 0;
}
There is no way to get out of the while loop.
I would write one more strtok in:
broken=strtok(strings, ",");
while(broken!=NULL){
strcpy( array[i][a], broken);
broken=strtok(NULL,",");
a++;
}
Related
Ive been trying various ways to get my program to work. regardless of weather i try argv1 or argv2 first, the second one will segmentation fault. even if i try to print SOURCE2DEFINE or argv[2] AFTER a move() it will segmentation fault. i cannot move both files trying to run move twice will result in a segmentation fault. im assuming that it has to be something to do with pointers and allocation.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/stat.h>
#define SOURCEDEFINE argv[1]
#define SOURCE2DEFINE argv[2]
#define DESTDEFINE argv[argc - 1]
#define ARGCDEFINE argc
#define COMMANDDEFINE argv[0]
int getIndex(char, char*);
char* fileGetName(char*);
void move(char*, char*);
void copy(char*, char*);
int main(int argc, char** argv)
{
printf("Test Argc: %d\n", argc);
int lengthArray = argc-2;
printf("Test Length: %d\n", lengthArray);
printf(" command %s\n", COMMANDDEFINE);
printf("%s\n", DESTDEFINE);
if(strcmp("./copy", COMMANDDEFINE) == 0)
{
// copy(source, dest);
}
else if(strcmp("./move", COMMANDDEFINE) == 0)
{
int i = 1;
printf("Test 1: %s\n", argv[i]);
printf("Test 2: %s\n", argv[argc-1]);
move(SOURCEDEFINE, DESTDEFINE);
printf("%s Filename debug \n", SOURCE2DEFINE);
move(SOURCE2DEFINE, DESTDEFINE);
// i++;
}
return 0;
}
void moveMultiple(int argc, char** argv){
int index = 1;
while(argv[index] != NULL){
if(index < argc - 1){
move(argv[index],argv[argc - 1]);
index++;
}
}
}
void move(char *source, char* dest)
{
printf("Running Move\n");
// FILE *s = fopen(source, "r");
// FILE *s;
//FILE *s = fopen(source, "r");
strcat(dest, fileGetName(source));
int l = link(source, dest);
//if(s == NULL)
if(l)
{
printf("Error, File Not Found");
perror("Link");
fflush(stdout);
exit(1);
}
remove(source);
}
void copy(char *source, char* dest)
{
printf("Running Copy\n");
strcat(dest, fileGetName(source));
int l = link(source, dest);
//if(s == NULL)
if(l)
{
printf("Error, File Not Found");
perror("Link");
fflush(stdout);
exit(1);
}
}
char* fileGetName(char *filename)
{
int i = 0;
int length = strlen(filename);
char *catString;
int index = getIndex('/', filename);
index--;
memcpy(catString,&filename[index], length);
return catString;
}
int getIndex(char i, char *s)
{
printf("Running getIndex\n");
int index = -1;
for(int l =0; l<strlen(s); l++){
if(s[l] == i) {
index = l;
}
}
return index;
}
Your move method changes dest (which is really argv[i]), and overwrites the memory after it: strcat(dest, fileGetName(source));. This destroys the other parameter and probably some other things. Don't write strings into memory you don't own.
can you advice me? I have a string from a file. When i see the string on my console, i need to write the word on which i want to change, and output the result in another file. For example: "Hello my girl" the word i want change "girl" on another word "boy". I can use the library
Can you advice me the algorithm which helps me to change the word?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
char my_string[256];
char* ptr;
FILE *f;
if ((f = fopen("test.txt", "r"))==NULL) {
printf("Cannot open test file.\n");
exit(1);}
FILE *out;
if((out=fopen("result.txt","w"))==NULL){
printf("ERROR\n");
exit(1);
}
fgets (my_string,256,f);
printf ("result: %s\n",my_string);
ptr = strtok (my_string," ");
while (ptr != NULL)
{
printf ("%s \n",ptr);
ptr = strtok (NULL," ");
}
char old_word [10];
char new_word [10];
char* ptr_old;
char* ptr_new;
printf ("Enter your old word:\n");
ptr_old= gets (old_word);
printf ("Your old word:%s\n",old_word);
printf ("Enter new old word:\n");
ptr_new = gets (new_word);
printf ("Your new word:%s\n",new_word);
fclose(f);
fclose(out);
return 0;
}
i tried to split inputting string into words. Now its dead end.
This code will help you. you have to pass 4 args at runtime.
./a.out "oldword" "newword" "file name from take the old word" "file name where to copy"
$ ./a.out girl boy test.txt result.txt
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int args, char *argv[4])
{
FILE *f1;
FILE *f2;
char *strings=0;
char *newstrings=0;
char *token=NULL;
strings=(char *)malloc(1000);
newstrings=(char *)malloc(1000);
if((strings==NULL)||(newstrings==NULL))
{
printf("Memory allocation was not successfull.");
return 0;
}
if(args<4)
{
puts("Error: Not enough input parameters");
puts("Usage: ./change <oldword> <newword> <infile> <newfile>");
return 0;
}
f1=fopen(argv[3],"r");
f2=fopen(argv[4],"w");
if(f1==NULL)
{
puts("No such file exists");
return 0;
}
while(fgets(strings,1000,f1)!=NULL)
{
if(strstr(strings,argv[1])!=NULL)
{
token=strtok(strings,"\n\t ");
while(token!=NULL)
{
if(strcmp(token,argv[1])==0)
{
strcat(newstrings,argv[2]);
strcat(newstrings," ");
}
else
{
strcat(newstrings,token);
strcat(newstrings," ");
}
token=strtok(NULL,"\n\t ");
}
}
else
{
strcpy(newstrings,strings);
}
fputs(newstrings,f2);
}
free(strings);
free(newstrings);
printf("New file <%s> generated!\n",argv[4]);
fclose(f1);
fclose(f2);
return 0;
}
You can use a function like the shown function in the demonstrative program below
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
char * replace(const char *s, const char *src, const char *dsn)
{
size_t n = 0;
size_t src_len = strlen(src);
size_t dsn_len = strlen(dsn);
for (const char *p = s; (p = strstr(p, src)) != NULL; p += src_len)
{
n++;
}
char *result = malloc(strlen(s) + n * (src_len - dsn_len) + 1);
const char *p = s;
char *t = result;
if (n != 0)
{
for (const char *q; (q = strstr(p, src)) != NULL; p = q + src_len)
{
memcpy(t, p, q - p);
t += q - p;
memcpy(t, dsn, dsn_len);
t += dsn_len;
}
}
strcpy(t, p);
return result;
}
int main( void )
{
char s[] = " the girl and boy are relatives";
char *p = replace(s, "girl", "boy");
puts(s);
puts(p);
free(p);
}
The program output is
the girl and boy are relatives
the boy and boy are relatives
#include <stdio.h>
#include <string.h>
int main ()
{
char file_path[40] = { 0 }, stf[255] = { 0 }, rtf[255] = { 0 }, str[255] = { 0 };
FILE* file = NULL;
FILE *e_f;
if((e_f=fopen("result.txt","w"))==NULL){
printf("ERROR\n");
exit(1);
}
do
{
printf("Enter file path: ");
fgets(file_path, 40, stdin);
file_path[strlen(file_path) - 1] = '\0';
file = fopen(file_path, "r+");
}
while(file == NULL);
printf("Enter text to find: ");
fgets(stf, 255, stdin);
stf[strlen(stf) - 1] = '\0';
printf("Enter text to replace: ");
fgets(rtf, 255, stdin);
rtf[strlen(rtf) - 1] = '\0';
while(fgets(str, 255, file) != NULL)
{
char* tmp_ptr = strstr(str, stf);
while(tmp_ptr != NULL)
{
char tmp_str[255];
strcpy(tmp_str, tmp_ptr + strlen(stf));
strcpy(str + strlen(str) - strlen(tmp_ptr), rtf);
strcat(str, tmp_str);
tmp_ptr = strstr(str, stf);
}
printf("%s", str);
}
fclose(file);
fclose(e_f);
return 0;
}
That was i need. Thanks everybody for helping!
I did a function:
#include <stdio.h>
#include <string.h>
#define MAX 50
void Change (char x[], char cx, char nu){
int i;
for(i=0;i<strlen(x);i++) {
if (x[i]==cx){
x[i] = nu;
}
}
}
int main () {
char str[MAX];
char ch;
char new;
printf("Insert the string\n");
scanf("%s",str);
printf("Insert the word that you want to change\n");
scanf(" %c",&ch);
printf("the new word\n");
scanf(" %c",&new);
Change(str, ch, new);
printf("The new word is %s\n",str );
return 0;
}
I must modify my program to accept input from
a file called anagrams.txt.This file should have two strings per line, separated by the # character. My program should read
each pair of strings and report back if each pair of strings is an anagram. For example consider the following content of anagrams.txt:
hello#elloh
man#nam
Astro#Oastrrasd
Your program should print out the following:
hello#elloh - Anagrams!
man#nam - Anagrams!
Astro#Oastrrasd- Not anagrams!
I should compile in g++
Here is the code to read from text:
int main()
{
char input[30];
if(access( "anagrams.txt", F_OK ) != -1) {
FILE *ptr_file;
char buf[1000];
ptr_file =fopen("anagrams.txt","r"); if (!ptr_file)
return 1;
while (fgets(buf,1000, ptr_file)!=NULL)
printf("%s",buf);
fclose(ptr_file);
printf("\n");
}
else{ //if file does not exist
printf("\nFile not found!\n");
}
return 0;
}
Code to find if the text are anagrams:
#include <stdio.h>
int find_anagram(char [], char []);
int main()
{
char array1[100], array2[100];
int flag;
printf("Enter the string\n");
gets(array1);
printf("Enter another string\n");
gets(array2);
flag = find_anagram(array1, array2);
if (flag == 1)
printf(" %s and %s are anagrams.\n", array1, array2);
else
printf("%s and %s are not anagrams.\n", array1, array2);
return 0;
}
int find_anagram(char array1[], char array2[])
{
int num1[26] = {0}, num2[26] = {0}, i = 0;
while (array1[i] != '\0')
{
num1[array1[i] - 'a']++;
i++;
}
i = 0;
while (array2[i] != '\0')
{
num2[array2[i] -'a']++;
i++;
}
for (i = 0; i < 26; i++)
{
if (num1[i] != num2[i])
return 0;
}
return 1;
}
You can try something like this:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#define MAXLINE 1000
#define MAXLETTER 256
int is_anagram(char *word1, char *word2);
void check_lines(FILE *filename);
int cmpfunc(const void *a, const void *b);
void convert_to_lowercase(char *word);
int
main(int argc, char const *argv[]) {
FILE *filename;
if ((filename = fopen("anagram.txt", "r")) == NULL) {
fprintf(stderr, "Error opening file\n");
exit(EXIT_FAILURE);
}
check_lines(filename);
fclose(filename);
return 0;
}
void
check_lines(FILE *filename) {
char line[MAXLINE];
char *word1, *word2, *copy1, *copy2;
while (fgets(line, MAXLINE, filename) != NULL) {
word1 = strtok(line, "#");
word2 = strtok(NULL, "\n");
copy1 = strdup(word1);
copy2 = strdup(word2);
convert_to_lowercase(copy1);
convert_to_lowercase(copy2);
if (is_anagram(copy1, copy2)) {
printf("%s#%s - Anagrams!\n", word1, word2);
} else {
printf("%s#%s - Not Anagrams!\n", word1, word2);
}
}
}
void
convert_to_lowercase(char *word) {
int i;
for (i = 0; word[i] != '\0'; i++) {
word[i] = tolower(word[i]);
}
}
int
is_anagram(char *word1, char *word2) {
qsort(word1, strlen(word1), sizeof(*word1), cmpfunc);
qsort(word2, strlen(word2), sizeof(*word2), cmpfunc);
if (strcmp(word1, word2) == 0) {
return 1;
}
return 0;
}
int
cmpfunc(const void *a, const void *b) {
if ((*(char*)a) < (*(char*)b)) {
return -1;
}
if ((*(char*)a) > (*(char*)b)) {
return +1;
}
return 0;
}
Since this looks like a University question, I won't provide a full solution, only a hint.
All you have to do is replace the stdin input part of the anagram-finding file with the code you wrote to read from a file: it's as simple as changing
printf("Enter the string\n");
gets(array1);
printf("Enter another string\n");
gets(array2);
to
// before program:
#define SIZE 1000
// inside main
if (access("anagrams.txt", F_OK) == -1){
printf("\nFile not found!\n");
return 1; // Abort the program early if we can't find the file
}
FILE *ptr_file;
char buf[1000];
ptr_file = fopen("anagrams.txt","r");
if (!ptr_file)
return 1;
char array1[SIZE], array2[SIZE];
while (fgets(buf, 1000, ptr_file)!=NULL){
// do all your anagram stuff here!
// there is currently one line of the input file stored in buf
// Hint: You need to split buf into array_1 and array_2 using '#' to separate it.
}
fclose(ptr_file);
printf("\n");
Additional comments:
Don't ever ever ever use gets. gets doesn't check that the string it writes to can hold the data, which will cause your program to crash if it gets input bigger than the array size. Use fgets(buf, BUF_SIZE, stdin) instead.
Beautiful code is good code. People are more likely to help if they can read your code easily. (fix your brackets)
Just for interest, a more efficient algorithm for checking anagrams is to use qsort to sort both arrays, then a simple string matcher to compare them. This will have cost O(mnlog(m+n)), as opposed to O(m^2 n^2), awith the current algorithm
You need to split every line you read by fgets (as you did) in to two strings, and pass them to your find_anagram function. You can do that using strtok:
int main()
{
int flag;
char buf[1000];
FILE *ptr_file;
//Check file existence
//Open the file for reading
while (fgets (buf, 1000, ptr_file) != NULL)
{
char *array1 = strtok(buf, "#");
char *array2 = strtok(NULL, "\n");
flag = find_anagram (array1, array2);
//Check flag value to print your message
}
return 0;
}
//put your find_anagram function
Don't forget to #include <string.h> to use strtok().
I was creating on a very basic program in C which takes a word from user as input and searches for how many times it appears in a text file and gives output.
The code is:
#include<stdio.h>
#include<string.h>
int main()
{
char user[20];
char word[20];
int i,pos=0,sum=0;
char c;
c='a';
printf("Enter the word you want to look for\n");
gets(user);
FILE *p;
p=fopen("D:\\trees.txt","r+");
do
{
pos=0;
fscanf(p,"%s",word);
if(c!=EOF)
{
if(strlen(word)==strlen(user))
{
for(i=0;i<strlen(user);i++)
{
if(word[i]==user[i]||word[i]==user[i]+32||word[i]==user[i]-32)
{
}
else
{
pos=1;
break;
}
}
}
else
{
pos=1;
}
if(pos=0)
{
sum++;
}
}
}
while(c!=EOF)
;printf("\nNumber of times %s appears is %d",user,sum);
fclose(p);
}
Now the program takes the input fine, but doesn't give any output.
Looks like this:
What have I done wrong?
Looking at the comments, your code should be something like:
#include<stdio.h>
#include<string.h>
#include <ctype.h>
int main()
{
char user[20];
char word[20];
int n, pos=0, sum=0;
unsigned int i, l;
FILE *p;
do {
printf("Enter the word you want to look for\n");
} while (gets(user)==0);
user[strlen(user)-1]= '\0'; // remove trailing \n
if ((p=fopen("D:\\trees.txt","r+"))==0) {printf("Error opening file\n"); exit(0);}
do
{
pos=0;
n= fscanf(p,"%s",word);
if (n==1)
{
if(strlen(word)==(l=strlen(user)))
{
for(i=0; i<l; i++)
{
if(!(word[i]==user[i]||word[i]==tolower(user[i])||word[i]==toupper(user[i])))
{
pos=1;
break;
}
}
}
else pos=1;
if(pos==0) sum++;
}
}
while(n==1);
printf("\nNumber of times %s appears is %d",user,sum);
fclose(p);
return(1);
}
(with some optimizations and additions)
Welcome everybody. I am new to Stackoverflow, I code in C for some time.
I have run to a problem writing a program counting word occurrences in a text file. I need to have an output telling what word occurred how many times. Here is the source code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int new_words=0;
int nwords=0;
typedef struct element{
char word[30];
int how_many;
} element;
int is_word_new(element ** dictionary, char * string)
{
for (int i =0; i<new_words; i++)
{
if (strcmp(string, dictionary[i]->word)==0)
return 0;
}
return 1;
}
int which_word(element ** dictionary, char * string)
{
for (int i =0; i<new_words; i++)
{
if (strcmp(string, dictionary[i]->word)==0)
return i;
}
return 0;
}
int main()
{
FILE * fp;
char word[30];
fp=fopen("input.txt", "r");
if (fp==NULL)
{
printf("FILE ERROR");
return 0;
}
while(!feof(fp))
{
fscanf(fp, "%s",word);
nwords++;
}
nwords--;
rewind(fp);
struct element * dictionary = (element*)malloc(sizeof(element)*nwords);
for (int i =0; i<nwords; i ++)
{
fscanf(fp, "%s", word);
if( is_word_new(&dictionary, word) )
{
strcpy(dictionary[new_words].word, word);
//dictionary[new_words].word= word;
dictionary[new_words].how_many=1;
new_words++;
}
else
dictionary[which_word(&dictionary, word)].how_many++;
word[0]='\0';
}
printf("\n\nFinal dictionary\n with %d words", new_words);
for (int i =0; i<new_words; i++)
{
printf("%s %d \n", dictionary[i].word, dictionary[i].how_many);
}
free(dictionary);
fclose(fp);
return 0;
}
the idea is that i first count how many words are in the text (which somehow is always greater by one than in fact). The function is_word_new checks if a newly read word is already in the dictionary. which_word() tells which word was found
However I get a segmentation fault running this program.
When I used the line which is commented // dictionary[i].word=word the program behaved as if there was only "word" in the dictionary.
Please give me hints where am I doing this stuff wrong
Must read question: Why is “while ( !feof (file) )” always wrong? Thanks to Jonathan Leffler's comment.
Please check my comments in the code below. I got you a start up for when the words are appearing once. I am letting the rest of the job for you, so that we can share the fun, but you can of course ask.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int new_words = 0;
int nwords = 0;
typedef struct element {
char word[30];
int how_many;
} element;
// no need to pass double pointer
int is_word_new(element* dictionary, char * string) {
int i;
for (i = 0; i < new_words; i++) {
printf("|%s|, |%s|\n", string, dictionary[i].word);
if (strcmp(string, dictionary[i].word) == 0)
return 0;
printf("i=%d\n",i);
}
return 1;
}
int which_word(element ** dictionary, char * string) {
int i;
for (i = 0; i < new_words; i++) {
if (strcmp(string, dictionary[i]->word) == 0)
return i;
}
return 0;
}
int main() {
FILE * fp;
char word[30];
fp = fopen("test.txt", "r");
if (fp == NULL) {
printf("FILE ERROR");
return 0;
}
printf("file read\n");
int read_counter;
while (!feof(fp)) {
read_counter = fscanf(fp, "%s", word);
// increment only if we really read something
if(read_counter >= 0)
nwords++;
}
// this is wrong, remove it
//nwords--;
rewind(fp);
printf("nwords = %d\n", nwords);
// do not cast what malloc returns. Also struct is not needed.
element * dictionary = malloc(sizeof (element) * nwords);
int i;
for (i = 0; i < nwords; i++) {
fscanf(fp, "%s", word);
printf("read |%s|\n", word);
if (is_word_new(dictionary, word)) {
strcpy(dictionary[new_words].word, word);
//dictionary[new_words].word= word;
dictionary[new_words].how_many = 1;
new_words++;
} else {
printf("bhka\n");
dictionary[which_word(&dictionary, word)].how_many++;
}
//word[0] = '\0';
}
printf("\n\nFinal dictionary\n with %d words", new_words);
for (i = 0; i < new_words; i++) {
printf("%s %d \n", dictionary[i].word, dictionary[i].how_many);
}
free(dictionary);
fclose(fp);
return 0;
}
Here is the test.txt I used:
sam klouvi george dit epfl
ok
end