Okay so basically the title says it all. I am working on a project where I get a segmentation fault right after I enter the name of the file I want to open. I created a smaller program that did just that, but when I implement it in my project it does not seem to work. I might be overlooking something. Would be awesome if someone could point it out.
#include<stdio.h>
#include<stdlib.h>
#include<ctype.h>
#include<string.h>
//function prototypes
void printmenu();
void getcipher(char **arr, int *count, FILE **infile);
int main()
{
int flag = 1; //exit flag for menu loop
int choices; //user input for menu
int count = 0;
char arr[7000][25]; //store words in this array
FILE *infile = NULL; //input cipher file
while(flag)
{
printmenu();
scanf("%d", &choices);
getchar();
while(choices < 1 || choices > 4)
{
printf("\nInvalid input. Try again...");
scanf("%d", &choices);
getchar();
}//end while
switch(choices)
{
case 1:
getcipher((char **)arr, &count, &infile);
break;
case 2:
printf("2");
break;
case 3:
printf("3");
break;
case 4:
flag = 0;
break;
}//end switch
}//end while
return 0;
}
void printmenu()
{
printf("\n%s", "Menu Choices");
printf("\n%-40s%-20s", "Use Cipher text file as cipher key", "Enter 1");
printf("\n%-40s%-20s", "Create cipher using a text file","Enter 2");
printf("\n%-40s%-20s", "Decode existing cipher", "Enter 3");
printf("\n%-40s%-20s\n\n", "Exit Program","Enter 4");
}
void getcipher(char **arr, int *count, FILE **infile)
{
int flag; //flag for getting cipher text file
char buffer[1000]; //buffer for reading in lines
char *token;
int letters = 0; //index for letters
int low; //index for converting to lowercase
//Gets cipher text file
printf("\nEnter the name of the cipher text file: ");
scanf("%s", buffer);
printf("\n%s\n", buffer);
*infile = fopen(buffer, "r");
if(!(*infile))
{
printf("Unable to open file. Exiting...");
exit(1);
}//end while
//inputs words from cipher text file to array
while(fgets(buffer, 1000, *infile))
{
token = strtok(buffer, " ");
strcat(arr[*count], token);
count++;
while((token = strtok(NULL, " ")) != NULL)
{
strcat(arr[*count], token);
count++;
}//end while
}//end while
printf("\n%d" , *count);
int i = 0;
//print array
while(i < *count)
{
printf("\n%s ", arr[i]);
i++;
}//end while
}
This is my second smaller program that opened a file within a function. I basically copied this into my project.
#include<stdio.h>
#include<string.h>
void openfile(FILE **file);
int main()
{
FILE *file = NULL;
openfile(&file);
return 0;
}
void openfile(FILE **file)
{
char buffer[100];
printf("Enter the name of file: ");
scanf("%s", buffer);
*file = fopen(buffer, "r");
if(*file)
printf("\nSuccess!!");
}
The problem is that you're casting arr, which is char [7000][25], to char ** when passing it to getcipher. These two declarations are incompatible. The first is a flat 2-dimensional array, while the second is an array of pointers, each of which points to its own secondary array. In general, if you are casting one pointer type to another like this, you are probably introducing a bug.
To fix it, you can change your char **arr declaration in getcipher to char arr[7000][25], or char arr[][25], or char (*arr)[25]. If you don't want to hard-wire the size, you can pass it as a parameter as long as it precedes the array parameter.
Second problem: You have argument int *count in getcipher. In this case it is a pointer to a single int. But you increment it with count++ in a couple places. This will increment the pointer, not the integer it points to. Change it to (*count)++;
Related
So a while ago I had someone make me a tool in C that lets you randomize set-words with other random words that you can both write down yourself in the program. However after 20 entries the program just freezes and crashes. I only have basic knowledge in coding can't couldn't see what was causing it. Maybe a memory overflow of some kind?
Here is the code. I can't reach the guy who wrote it anymore so if someone could have a look I would greatly appreciate it a lot!
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <malloc.h>
#define BUFFER_SIZE 1000
void replaceAll(char *str, const char *oldWord, const char *newWord);
int main()
{
int updates=0;
char **upd_array ;
printf("Enter number of words for replacements: ");
scanf("%d", &updates);
upd_array=(char**)malloc(updates+1*sizeof(char*));
//upd_array = calloc(updates, sizeof *upd_array);
int x=0;
for(x=0 ; x<updates ; x++)
{
upd_array[x] = (char*)malloc(30*sizeof(char));
}
int i=0;
for(i=0 ; i<updates ; i++)
{
printf("Enter word: \n");
scanf("%s" ,upd_array[i]);
}
printf("list of word for updating");
printf("\n");
for(i=0 ; i<updates ; i++)
{
printf("%s",upd_array[i]);
printf("\n");
}
int count=0;
do{
/* File pointer to hold reference of input file */
FILE * fPtr;
FILE * fTemp;
char path[100];
char buffer[BUFFER_SIZE];
char oldWord[100], newWord[100];
printf("Enter path of source file: ");
scanf("%s", path);
printf("Enter word to replace: ");
scanf("%s", oldWord);
/* Open all required files */
fPtr = fopen(path, "r");
fTemp = fopen("replace.tmp", "w");
/* fopen() return NULL if unable to open file in given mode. */
if (fPtr == NULL || fTemp == NULL)
{
/* Unable to open file hence exit */
printf("\nUnable to open file.\n");
printf("Please check whether file exists and you have read/write privilege.\n");
exit(EXIT_SUCCESS);
}
/*
* Read line from source file and write to destination
* file after replacing given word.
*/
while ((fgets(buffer, BUFFER_SIZE, fPtr)) != NULL)
{
// Replace all occurrence of word from current line
int r = rand() % updates;
strcpy(newWord , upd_array[r]);
replaceAll(buffer, oldWord, newWord);
// After replacing write it to temp file.
fputs(buffer, fTemp);
}
/* Close all files to release resource */
fclose(fPtr);
fclose(fTemp);
/* Delete original source file */
remove(path);
/* Rename temp file as original file */
rename("replace.tmp", path);
printf("\nSuccessfully replaced all occurrences of '%s'.\n", oldWord);
printf("1 for continue 0 for terminate: ");
scanf("%d", &count);
}while(count);
free(upd_array);
return 0;
}
/**
* Replace all occurrences of a given a word in string.
*/
void replaceAll(char *str, const char *oldWord, const char *newWord)
{
char *pos, temp[BUFFER_SIZE];
int index = 0;
int owlen;
//printf("in replace function");
owlen = strlen(oldWord);
/*
* Repeat till all occurrences are replaced.
*/
while ((pos = strstr(str, oldWord)) != NULL)
{
// Backup current line
strcpy(temp, str);
// Index of current found word
index = pos - str;
// Terminate str after word found index
str[index] = '\0';
// Concatenate str with new word
strcat(str, newWord);
// Concatenate str with remaining words after
// oldword found index.
strcat(str, temp + index + owlen);
}
}
Looks like the memory allocation has the issue.
upd_array=(char**)malloc(updates+1*sizeof(char*));
should be
upd_array= malloc( (updates+1)*sizeof(char*) );
or better,
upd_array= malloc( (updates+1)* sizeof(*upd_array) );
or
upd_array= malloc( (updates+1)* sizeof*upd_array );
Then,
scanf("%s" ,upd_array[i]);
should at least be
scanf("%29s" ,upd_array[i]); //stop buffer overflow
and you must check the return value for success.
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().
my question is as follows:
For school I have to make a little program in C to create and modify .txt files. I have gotten to create the file and write on it but when I read from it to print on the screen It doesn't do from the beginning and then the "fisical" file in my computer is all corrupted with chinese characters...
I don't know what's going on... Here's my code:
#include <stdio.h>
#include <conio.h>
#include <string.h>
#include <unistd.h>
#define SIZE 1
void clrscr()
{
system("cls");
}
int getLenght(char *Rstring)
{
int n = 0;
while(Rstring[n] != '\0')
n++;
return n;
}
void getPath(char fname[])
{
printf("Insert file path: ");
gets(fname);
fflush(stdin);
}
// Returns 0 DOESNT EXIST, 1 DOES EXIST
int fileExist(char *fname)
{
if(access(fname, F_OK) != -1)
return 1;
return 0;
}
//if manage file is NULL truncate program
FILE *manageFile(char *fname)
{
if(fileExist(fname))
return fopen(fname, "r+");
else
return fopen(fname, "w+");
}
//Returns 1 if there's an ERROR 0 if NOT
int readFile(FILE *streamf, char buffer[])
{
fflush(streamf);
fseek(streamf, -1, SEEK_SET);
fread(buffer, SIZE, sizeof(buffer), streamf);
if(ferror(streamf)){
clearerr(streamf);
return 1;
}
return 0;
}
//Returns 1 if there's an ERROR 0 if NOT
int writeFile(FILE *streamf, char buffer[])
{
int NELEMT;
printf("Insert text to input file:\n");
gets(buffer);
fflush(stdin);
NELEMT = getLenght(buffer);
fflush(streamf);
fseek(streamf, 1, SEEK_END);
fwrite(buffer, SIZE, NELEMT, streamf);
if(ferror(streamf)){
clearerr(streamf);
return 1;
}
return 0;
}
int main()
{
char fname[1000];
char buffer[1000];
char choice;
int CC = 1;
FILE *streamf = NULL;
printf("\tFILE MANAGMENT SYSTEM TEST v 1.0\n");
getPath(fname);
streamf = manageFile(fname);
if(streamf == NULL){
printf("\n\nFILE OPEN ERROR! Terminate Program");
CC = 0;
}
while(CC == 1){
clrscr();
printf("\tFILE MANAGMENT SYSTEM TEST v 1.0 - MENU\nCURRENT PATH: %s\n\n", fname);
printf("1. Read File\n2. Write File\n3. Close File\n");
choice = getch();
fflush(stdin);
switch(choice)
{
case '1':
if(readFile(streamf, buffer))
printf("\n\nREAD FILE ERROR!");
else
printf("Successfully read from the file:\n%s", buffer);
getch();
break;
case '2':
if(writeFile(streamf, buffer))
printf("\n\nWRITE FILE ERROR!");
else
printf("Successful file input");
getch();
break;
case '3':
fflush(streamf);
fclose(streamf);
CC = 0;
break;
default:
printf("\n\nOPTION NOT LISTED");
getch();
}
}
return 0;
}
You're using sizeof(buffer) in the call to fread but it's not doing what you think. Look at how you pass buffer into readFile:
int readFile( FILE *streamf, char buffer[] );
This means that buffer is just a pointer, and so sizeof(buffer) will be equal to sizeof(char*). It's a classic mistake people make with sizeof so this is a rite of passage for you.
You will need to actually pass in a size to your function, or redefine it to accept char buffer[1000]. I would pass a size explicitly though:
int readFile( FILE *streamf, char buffer[], size_t buffer_size );
Also, as appeared in the comments, you are using fseek incorrectly. You need to use an offset of 0 with both SEEK_SET and SEEK_END.
The problem statement : a C program to count the number of times a character appears in the File. character is considered Case insensitive.
I have converted both the input character and character from the file to upper case so that none of the occurrence of the character goes uncounted. but when am executing this on an online editor am getting the result as "wrong answer" the editor isn`t accepting this code. what is the mistake in this code??
#include<stdio.h>
#include<ctype.h>
#include<stdlib.h>
int main
{
FILE *fp;
char filename[20];
char character;
char compare;
int to_upper1;
int to_upper2;
int count=0;
printf("\nEnter the file name");
scanf("%s", filename);
fp = fopen(filename,"r");
if(fp == NULL)
{
exit(-1);
}
printf("\nEnter the character to be counted");
scanf("%c", &character);
to_upper1 = toupper(character);
while((compare = fgets(fp)) != EOF)
{
to_upper2 = toupper(compare);
if(to_upper1 == to_upper2)
count++;
}
printf("\nFile \'%s\' has %d instances of letter \'%c\'", filename, count, character);
return 0;
}
I found a few errors in your code, and made a few small tweaks. The errors are - not eating the "whitespace" before the character input, using fgets() instead of fgetc(), using escape characters before the ' symbols in the output text.
#include <stdio.h>
#include <ctype.h>
#include <stdlib.h>
int main(void) // added arg for compilability
{
FILE *fp;
char filename[20];
char character;
int compare; // correct type for fgetc and toupper
int to_upper1;
int to_upper2;
int count=0;
printf("Enter the file name: ");
scanf("%19s", filename); // restrict length
fp = fopen(filename,"r");
if(fp == NULL)
{
printf ("Cannot open file '%s'\n", filename);
exit(-1);
}
printf("\nEnter the character to be counted: ");
scanf(" %c", &character); // filter out whitespace
to_upper1 = toupper((int)character);
while((compare = fgetc(fp)) != EOF) // changed from fgets()
{
to_upper2 = toupper(compare);
if(to_upper1 == to_upper2)
count++;
}
fclose(fp); // remember to close file!
printf("File '%s' has %d instances of letter '%c'", filename, count, character);
return 0;
}
#include<stdio.h>
#include<stdlib.h>
#include<ctype.h>
int main()
{
FILE *fptr;
int d=0;
char c;
char ch,ck;
char b[100];
printf("Enter the file name\n");
scanf("%19s",b);
fptr=fopen(b,"r");
printf("Enter the character to be counted\n");
scanf(" %c",&c);
c=toupper(c);
if(fptr==NULL)
{
exit(-1);
}
while((ck=fgetc(fptr))!=EOF)
{
ch=toupper(ck);
if(c==ch||c==ck)
++d;
}
fclose(fptr);
printf("File '%s' has %d instances of letter '%c'.",b,d,c);
return(0);
}
I'm currently trying to make a program that will read a file find each unique word and count the number of times that word appears in the file. What I have currently ask the user for a word and searches the file for the number of times that word appears. However I need the program to read the file by itself instead of asking the user for an individual word.
This is what I have currently:
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char const *argv[])
{
int num =0;
char word[2000];
char *string;
FILE *in_file = fopen("words.txt", "r");
if (in_file == NULL)
{
printf("Error file missing\n");
exit(-1);
}
scanf("%s",word);
printf("%s\n", word);
while(!feof(in_file))//this loop searches the for the current word
{
fscanf(in_file,"%s",string);
if(!strcmp(string,word))//if match found increment num
num++;
}
printf("we found the word %s in the file %d times\n",word,num );
return 0;
}
I just need some help figuring out how to read the file for unique words (words it hasn't checked for yet) although any other suggestions for my program will be appreciated.
If you want to print every line contained in the file just once, you have to save the strings you have read in a given data structure. For example, a sorted array could do the trick. The code might look as follow:
#include <stddef.h>
size_t numberOfLine = getNumberOfLine (file);
char **previousStrings = allocArray (numberOfLine, maxStringSize);
size_t i;
for (i = 0; i < numberOfLine; i++)
{
char *currentString = readNextLine (file);
if (!containString (previousStrings, currentString))
{
printString (currentString);
insertString (previousStrings, currentString);
}
}
You may use binary search to code the functions containString and insertString in an efficient way. See here for further informations.
You have to split your code into functions (subroutines).
One function would read the file and record all words; the other would count the number of occurrences for each word.
int main(int argc, char const *argv[])
{
char *words[2000];
// Read the file; store all words in the list
int number_of_words = ReadWords("words.txt", words, 2000);
// Now count and print the number of occurrences for each word
for (int i = 0; i < number_of_words; i++)
{
int n = CountOccurrences(words[i], "words.txt");
printf("we found the word %s in the file %d times\n", words[i], n);
}
// Deallocate dynamically allocated memory
Cleanup(words, number_of_words);
}
Note how the main function is relatively short. All the details are in the functions ReadWords and CountOccurrences.
To implement reading all words from a file:
int ReadWords(const char *filename, char *words[], int max_number_of_words)
{
FILE *f = fopen(filename, "rt"); // checking for NULL is boring; i omit it
int i;
char temp[100]; // assuming the words cannot be too long
for (i = 0; i < max_number_of_words; ++i)
{
// Read a word from the file
if (fscanf(f, "%s", temp) != 1)
break;
// note: "!=1" checks for end-of-file; using feof for that is usually a bug
// Allocate memory for the word, because temp is too temporary
words[i] = strdup(temp);
}
fclose(f);
// The result of this function is the number of words in the file
return i;
}
`#include <stdio.h>
#include <stdlib.h>
int main(int argc, char*argv[])
{
int num =0;
char word[2000];
char string[30];
FILE *in_file = fopen(argv[1], "r");
if (in_file == NULL)
{
printf("Error file missing\n");
exit(-1);
}
scanf("%s",word);
printf("%s\n", word);
while(!feof(in_file))//this loop searches the for the current word
{
fscanf(in_file,"%s",string);
if(!strcmp(string,word))//if match found increment num
num++;
}
printf("we found the word %s in the file %d times\n",word,num );
return 0;
}`
if any suggestion plz..most welcome
Blockquote