I keep getting a segmentation fault with this code that I am trying to get to print the first 6 words of the dictionary. I'm pretty sure I'm using fscanf incorrectly but I'm not sure how/why...
#define _XOPEN_SOURCE
#include <unistd.h>
#include <stdio.h>
int main(int argc, char* enc[])
{
if (argc != 2)
{
printf("Improper command-line arguments\n");
return 1;
}
FILE *Dict;
Dict = fopen("/usr/share/dict/words", "r");
if (Dict == NULL)
{
printf("Could not open dictionary");
exit(1);
}
char* full = enc[1];
char* salt[2];
for (int i=0; i<2; i++)
{
salt[i] = &full[i];
}
char* key[50];
for (int i=0; i<6; i++)
{
fscanf(Dict, "%s", *key);
printf("%s", *key);
}
}
C strings are either a character array: char name[10], or pointer-to-char (which points to a valid range of memory): char* name.
What you have here is an array of 50 pointers to characters (or strings):
char* key[50];
for (int i=0; i<6; i++)
{
fscanf(Dict, "%s", *key);
printf("%s", *key);
}
key is probably intended to be a 50-character C string buffer:
char key[50];
for (int i=0; i<6; i++)
{
fscanf(Dict, "%s", key);
printf("%s", key);
}
Related
I have an unknown segfault within my print function when I call it in main and I can't see what the obvious fix is. I have put printf's throughout the program and it doesn't print 'here4' making me think it's due to my print function, or when I call it in main.
I want to read a dictionary file into an array of strings.
Here is a snippet of the code:
Any ideas would be greatly appreciated, thanks.
#define PRIME 1009
void fileRead(int argc, char **argv)
void printTable(int arrayLength, char **table);
int main(int argc, char **argv)
{
char **table;
FILE *fp;
int i, arrayLength = PRIME;
/* Initial memory allocation */
table = (char**)malloc(PRIME*sizeof(char));
fileRead(argc, argv);
printf("here3\n");
for(i = 0; i < arrayLength; i++) {
printTable(arrayLength,table);
}
printf("here4\n");
return 0;
}
void fileRead(int argc, char **argv)
{
FILE *fp;
char *word;
int arrayLength = PRIME;
word = calloc(MAXCHAR, sizeof(char));
fp = fopen (argv[1], "r");
printf("here1\n");
/*read in grid and move along a cell each time */
while (fscanf(fp, "%s", word)!= EOF) {
if (argc != (2)) {
fprintf(stderr, "Cannot open file, %s\n Try again e.g. %s dictionary.txt\n" , argv[1], argv[0]);
}
if(fp == NULL) {
fprintf(stderr, "Cannot open file, %s\n Try again e.g. %s dictionary.txt\n" , argv[1], argv[0]);
return;
}
if (fp == NULL) {
fprintf(stderr, "Error opening file, try file name dictionary.txt\n");
exit(EXIT_FAILURE);
}
}
printf("here2\n");
fclose(fp);
return;
}
void printTable(int arrayLength, char **table)
{
int i;
for(i = 0; i < arrayLength; i++) {
printf("%s\n", table[i]);
}
printf("\n");
}
Let me summarize your code:
you allocate uninitialized memory for table
You call a function fileRead():
Allocate some memory for word
read the file
Do nothing with the data read.
fileRead() does nothing useful: It does not return anything, it doesn't touch table, is vulnerable to a buffer overflow of word and leaves the memory leak of word behind.
And then you printf the unchanged and uninitialized content of table
try this
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define PRIME 1009
#define MAXCHAR 256
char **fileRead(FILE *fp, int *len);
void printTable(int arrayLength, char **table);
int main(int argc, char **argv){
if (argc != 2) {
fprintf(stderr, "Need dictionary file argument.\nTry again e.g. %s dictionary.txt\n" , argv[0]);
exit(EXIT_FAILURE);
}
FILE *fp = fopen (argv[1], "r");
if(fp == NULL) {
fprintf(stderr, "Cannot open file, %s\nTry again e.g. %s dictionary.txt\n" , argv[1], argv[0]);
exit(EXIT_FAILURE);
}
int arrayLength = PRIME;
char **table = fileRead(fp, &arrayLength);//fclose(fp) inside this
printTable(arrayLength, table);
for(int i = 0; i < arrayLength; ++i)
free(table[i]);
free(table);
return 0;
}
char **fileRead(FILE *fp, int *len){
char *word = calloc(MAXCHAR, sizeof(char));
char **table = malloc(*len * sizeof(char*));
int i = 0;
while (i < *len && fscanf(fp, "%s", word) != EOF){
table[i] = malloc(strlen(word)+1);
strcpy(table[i++], word);
}
fclose(fp);
*len = i;
free(word);
return table;
}
void printTable(int arrayLength, char **table){
int i;
for(i = 0; i < arrayLength; i++) {
printf("%s\n", table[i]);
}
printf("\n");
}
I am taking the lines from a text file and storing the lines in an array. Then I am splitting the lines into separate words and storing them in another array. But I have a problem with the words stored.
Text file content:
ls -l hahaha
Code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char *trim (char *s) {
int i = strlen(s)-1;
if ((i > 0) && (s[i] == '\n'))
s[i] = '\0';
return s;
}
int main(int argc, char *argv[]){
FILE *fp;
char *output = NULL;
fp= fopen("ints.txt", "r");
//fscanf and fprintf is used for files and is same is printf and scanf
fprintf(fp, "Testing...\n");
//fgetsc for single character in file and fputc to write
//
size_t len = 0;
ssize_t read;
const char s[2]=" ";
char *token;
char line[256];
char *lines[10];
char *eof;
char *args[10];
//=====nulling the array lines====
for(int p=0; p<10; p++)
{
lines[p]=NULL;
}
int i=0;
if (fp == NULL)
{
exit(EXIT_FAILURE);
}
else
{
while(fgets(line, 256, fp)!= NULL)
{
lines[i] = strdup(line);
//printf("%s", lines[i]);
i++;
}
}
fclose(fp);
int k=0;
for(int j=0; j<9; j++)
{
if(lines[j]!=NULL)
{
token =strtok(lines[j], s); //s is the delimiter
while(token != NULL)
{
trim(token);
//printf("%s\n", token);
args[k] = token;
token = strtok(NULL,s);
k++;
}
}
}
printf("%s\n",args[0]);
printf("%s\n", args[1]);
printf("%s\n", args[2]);
printf("%s something\n", args[0]);
printf("%s something\n" , args[2]);
printf("program done\n");
}
Output:
ls
-l
hahaha
ls something
something //the hahaha part disappears for the last printf**
program done
I'm having real trouble working with strings and string arrays, and using strcpy correctly. I'm using a dictionary of words scanned in a 2D array dictionary. Then I take a start word, alter every letter of it to create many different variants, i.e cat -> cbt, cct, cdt, etc. From there I copy each generated word into a 2D array and to compare these generated words to the dictionary to see if they are real words. I then want to print these real words, i.e cat as a start word will generate bat if its in the dictionary, but zat won't be. When I run the code it prints all the generated words but when It gets to check_dictionary function it prints no words.
The text file it reads from is like:
mat
yes
cat
hat
The code:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define MAX_WORDS 20000
#define MAX_WORD_LENGTH 30
#define ARGS_REQUIRED 2
typedef struct scanned_words
{
char startword[MAX_WORD_LENGTH];
char endword[MAX_WORD_LENGTH];
} Scanned_words;
Scanned_words scan_two_words(Scanned_words words);
void get_next_word(Scanned_words words,
char parentwords[MAX_WORDS][MAX_WORD_LENGTH]);
void read_file(char * argv[], char dictionary[MAX_WORDS][MAX_WORD_LENGTH]);
void check_dictionary(char dictionary[MAX_WORDS][MAX_WORD_LENGTH],
char parentwords[MAX_WORDS][MAX_WORD_LENGTH]);
void usage(char * argv[]);
int main(int argc, char * argv[])
{
char dictionary[MAX_WORDS][MAX_WORD_LENGTH];
char nextword[MAX_WORDS][MAX_WORD_LENGTH];
char parentwords[MAX_WORDS][MAX_WORD_LENGTH];
Scanned_words words;
if (argc == ARGS_REQUIRED)
{
system("clear");
read_file(&argv[1], dictionary);
words = scan_two_words(words);
get_next_word(words, parentwords);
check_dictionary(dictionary, parentwords);
}
else
{
usage(&argv[0]);
}
return 0;
}
void read_file(char * argv[], char dictionary[MAX_WORDS][MAX_WORD_LENGTH])
//reads the text file and stores the dictonary as a 2D array
{
FILE * file_name;
int word_count = 0, i;
if ((file_name = fopen(argv[0], "r")) == NULL )
{
printf("Cannot open file ... \n");
}
while (fscanf(file_name, "%s", dictionary[i++]) == 1)
{
printf("%s ", dictionary[word_count]);
word_count++;
}
printf("\n");
printf("\n%d words scanned in from: %s\n\n", word_count, argv[0]);
}
Scanned_words scan_two_words(Scanned_words words)
//takes an empty structure, scans both words in and returns them in the same structure
{
printf("Enter the start word: \n");
scanf("%s", words.startword);
printf("\nEnter the end word: \n");
scanf("%s", words.endword);
printf("\n");
return words;
}
void get_next_word(Scanned_words words,
char parentwords[MAX_WORDS][MAX_WORD_LENGTH])
//get all eligible second words from original start word
{
char character;
char currentword[MAX_WORD_LENGTH];
int i;
strcpy(currentword, words.startword);
for (i = 0; currentword[i] != '\0'; i++)
{
strcpy(currentword, words.startword);
for (character = 'a'; character <= 'z'; character++)
{
currentword[i] = character;
strcpy(parentwords[i], currentword);
printf("%s ", parentwords[i]);
}
}
parentwords[i][0] = '\0';
printf("\n\n");
}
void check_dictionary(char dictionary[MAX_WORDS][MAX_WORD_LENGTH],
char parentwords[MAX_WORD_LENGTH][MAX_WORD_LENGTH])
//checks a generated word for eligibility against the dictionary, prints next generation words
{
int i, j;
printf("\nSecond words: \n\n");
for (j = 0; parentwords[j][0] != '\0'; j++)
;
{
for (i = 0; dictionary[i][0] != '\0'; i++)
{
if ((strcmp(dictionary[i], parentwords[j])) == 0)
{
printf("%s \n", parentwords[j]);
}
}
}
}
void usage(char * argv[])
//prints error message
{
printf("Incorrect usage, try: ./program_name %s\n", argv[1]);
}
The formatting revealed this:
for (j = 0; parentwords[j][0] != '\0'; j++)
;
which most probably was meant to be:
for (j = 0; parentwords[j][0] != '\0'; j++)
Here
while (fscanf(file_name, "%s", dictionary[i++]) == 1)
the i is used uninitialised
So change it definition to include an initialisation:
int word_count = 0, i = 0;
Im trying to sort a array of strings I read from a file in alphabetical order using the qsort function. This is my code:
#include<stdio.h>
#include<stdlib.h>
#include<io.h>
#define MAXCHAR 256
int main(int argc, char **argv){
char tempList[MAXCHAR][MAXCHAR];
char reader[MAXCHAR];
FILE* fp;
int i;
char *n;
int index = 0;
if(argc != 2){
printf("too few arguments\n");
exit(-1);
}
fp=fopen(argv[1], "r");
if(fp == NULL){
printf("failed to open file\n");
exit(-1);
}
while(!feof(fp)){
fgets(reader, MAXCHAR, fp);
n = strchr(reader, '\n');
if(n != NULL){
*n = '\0';
}
strcpy(tempList[index], reader);
index++;
}
index--;
for(i=0; i<index; i++){
printf("%s\n", tempList[i]);
}
qsort(tempList, index, sizeof(char *), strcmp);
for(i=0; i<index; i++){
printf("%s\n", tempList[i]);
}
}
When I run the program, the list doesn't get sorted at all. I also tried methods posted on this website that asks a similar question and they all give me segmentation faults. Is there something wrong with the code?
Here is part of the content of the txt file. It is a list of 40 names:
Liam
Alexander
Mia
Noah
Emma
William
Charlotte
Charlotte
Mason
William
Ethan
Ethan
Liam
Alexander
Liam
Sophia
Emily
Mason
Alexander
You have a bona fide array of arrays; not an array of char*. Arrays aren't pointers. qsort expects the stride of the elements in the sequence being sorted. As your sequence is declared as:
char tempList[MAXCHAR][MAXCHAR];
the proper element size is the size of the inferior element size. In this case you have an array of size MAXCHAR of array of char of size MAXCHAR (an array of arrays).
Thus this is wrong:
qsort(tempList, index, sizeof(char *), strcmp);
// wrong size ==============^^^^
the size of each element should be:
qsort(tempList, index, sizeof tempList[0], strcmp);
// correct size ==============^^^^
The other issues in your program will eventually grief you and are covered in general comments below your question, but this is the fundamental problem preventing your sorting from working correctly. A retooled version of your program appears below, addressing most of those concerns:
Updated Source
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAXCHAR 256
/* properly declared for compatibility with qsort */
static int cmp_str(const void *lhs, const void *rhs)
{
return strcmp(lhs, rhs);
}
/* main entrypoint */
int main(int argc, char **argv)
{
char tempList[MAXCHAR][MAXCHAR];
FILE* fp;
size_t i, index = 0;
if(argc != 2)
{
printf("too few arguments\n");
return EXIT_FAILURE;
}
fp=fopen(argv[1], "r");
if(fp == NULL)
{
perror(argv[1]);
return EXIT_FAILURE;
}
while(index < MAXCHAR && fgets(tempList[index], sizeof(*tempList), fp) != NULL)
{
char *n = strchr(tempList[index], '\n');
if(n != NULL)
*n = 0;
if (*(tempList[index])) /* don't insert blank lines */
++index;
}
for(i=0; i<index; i++)
printf("%s\n", tempList[i]);
fputc('\n', stdout);
qsort(tempList, index, sizeof tempList[0], cmp_str);
for(i=0; i<index; i++)
printf("%s\n", tempList[i]);
return EXIT_SUCCESS;
}
Untested, but it should be pretty close.
Best of luck.
Your size value in qsort(tempList, index, sizeof(char *), strcmp); is wrong.
It should be qsort(tempList, index, sizeof(*tempList), strcmp);.
I have tried to fix your code.
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
//#include<io.h> it's not standart
#define MAXCHAR 256
// I implement the function because the warning is that
// Incompatible pointer types passing 'int
// (const char *, const char *)' to parameter of type
// 'int (*)(const void *, const void *)'
// Already qsort() prototype is
// void qsort(void* ptr, size_t count, size_t size,
// int (*comp)(const void*, const void*));
// I think that the warning can be ignored strcmp also can be used
int myCompare(const void* a, const void* b)
{
const char* aa = (const char*)a;
const char* bb = (const char*)b;
return strcmp(aa, bb);
}
int main(int argc, char **argv){
char tempList[MAXCHAR][MAXCHAR];
char reader[MAXCHAR];
FILE* fp;
int i;
char *n;
int index = 0;
if(argc != 2){
printf("too few arguments\n");
exit(-1);
}
fp=fopen(argv[1], "r");
if(fp == NULL){
printf("failed to open file\n");
exit(-1);
}
while(fgets(reader, MAXCHAR, fp) != NULL){ // !feof is not recommended search why
n = strchr(reader, '\n');
if(n != NULL){
*n = '\0';
}
strcpy(tempList[index], reader);
index++;
}
/*
printf("%lu\n",sizeof(reader)); //256
printf("%lu\n",sizeof(*reader)); //1
printf("%lu\n",sizeof(*tempList)); //256
printf("%lu\n",sizeof(**tempList)); //1
*/
for(i=0; i<index; i++){
printf("%s\n", tempList[i]);
}
qsort(tempList, index, sizeof(*tempList), myCompare);
printf("\n\nAfter sorting\n\n");
for(i=0; i<index; i++){
printf("%s\n", tempList[i]);
}
}
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