i'm trying to fill each row of the array with each word of the file.
I don't want to overallocate memory , so i want to know atleast the lenght of the longest word and the number of rows i should allocate, so the number of words written in the file.
I can't understand where is the problem in the code. I think it should be a problem with counting the longest word since when i print longest_file_word after assigning the value returned by the function it prints -1.
Obviously it doesnt work.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
int longestWord(char *file, int *nWords);
char ** Create2DStr(ssize_t numStrings, ssize_t maxStrLen);
int main(int argc, char *argv[]){
int file_elements_number=0 , i , j , k , z , longest_file_word , count_file_words ;
char *filename =(char*)malloc((strlen(argv[2]) +1 )*sizeof(filename));
strcpy( filename , argv[1]);
for(i = 0; i < strlen(argv[1])+1 ; i++){
printf("%c" , filename[i]);
}
if(filename = NULL){
printf("Non c'e' abbastanza memoria");
return 1;
}
if(argc!=2)
{
printf("Errore numero parametri passati da linea di comando\n");
return 1;
}
longest = longestWord( filename , &count);
printf("ciao %d\n%d\n", count , longest);
char **file_words = Create2DStr(count, longest);
FILE *file_ptr;
const char delim[] = {" \n\t"};
char line[260];
char *buf = NULL;
file_ptr = fopen( filename, "r");
count=0;
while(fgets(line, 260, file_ptr))
{
buf = strtok(line, delim);
while(buf)
{
if((strlen(buf) > 0)){
strcpy(file_words[count], buf);
count++;
}
buf = strtok(NULL, delim);
}
}
for(i = 0 ; i < count ; i++){
for( j = 0 ; j < longest ; j++){
printf("%c" , file_words[i][j]);
}
printf("\n");
}
fclose(file_ptr);
free(filename);
filename = NULL;
return 0;
}
int longestWord(char *filename, int *nWords)
{
FILE *file_ptr=0;
int cnt=0, longest=0, numWords=0;
char c;
file_ptr = fopen(filename, "r");
if(file_ptr){
while ( (c = fgetc(file_ptr) ) != EOF )
{
if ( isalnum (c) ) {
cnt++;
}
else if ( ( ispunct (c) ) || ( isspace(c) ) || (c == '\0' ) || (c== '\n'))
{
(cnt > longest) ? (longest = cnt, cnt=0) : (cnt=0);
numWords++;
}
}
*nWords = numWords;
fclose(file_ptr);
}
else {
return -1;
}
return longest;
}
char ** Create2DStr(ssize_t numStrings, ssize_t maxStrLen){
int i;
char **a = {0};
a =(char**) calloc(numStrings, sizeof(a));
for(i=0;i<numStrings; i++)
{
a[i] = (char*)calloc(maxStrLen + 1, 1);
}
return a;
}
You're doing,
if(filename = NULL)
rather than,
if(filename == NULL)
after reading your filename.
You should be compiling with warnings turned on, -Wall on gcc.
The result -1 means that function longestWord cannot open the specified file name which may be a result of the if(filename = NULL)
Apart from this it is difficult to understand what you are doing with argv[1] and argv[2] to prepare filename. You allocate memory based on the string length of argv[2], then copy the string from argv[1] which could be longer.
You should do the checks of argc and filename before you access argv or filename.
Related
I wrote the next function that tries to read and enter each line from text file into a string array in c :
int main(int argc,char* argv[])
{
char ** lines;
readFile(argv[1],lines);
}
int readFile(char* filePath,char** lines)
{
char file_char;
int letter_in_line=0;
int line=1;
char* line_string=malloc(1024);
int j=1;
int fd=open(filePath,O_RDONLY);
if (fd < 0)
{
return 0;
}
while (read(fd,&file_char,1) >0)
{
if(file_char != '\n' && file_char != '0x0')
{
line_string[letter_in_line] = file_char;
letter_in_line++;
}
else
{
if(lines != NULL)
{
lines=(char**)realloc(lines,sizeof(char*)*line);
}
else
{
lines=(char**)malloc(sizeof(char*));
}
char* line_s_copy=strdup(line_string);
lines[line-1]=line_s_copy;
line++;
letter_in_line=0;
memset(line_string,0,strlen(line_string));
}
j++;
}
printf("cell 0 : %s",lines[0]);
return 1;
}
I have 2 questions :
1)Whenever the code reaches the print of cell 0, I'm getting
Segmentation fault (core dumped) error. What is wrong ?
2)In case I
want to see the changes in the lines array in my main, I should pass
&lines to the func and get char*** lines as an argument ? In
addition, I will need to replace every 'line' keyword with '*line' ?
*I know that I can use fopen,fget, etc... I decided to implement it in this way for a reason.
There is many issues that make your code core dump.
Here a version very similar to your code. I hope it will help you to understand this.
#include <stdio.h>
#include <string.h>
#include <fcntl.h>
#include <stdlib.h>
int read_file(const char *filename, char ***result)
{
/* open the file */
const int fd = open(filename, O_RDONLY);
if (fd < 0) {
*result = NULL;
return -1;
}
/* read the file characters by characters */
char *buffer = (char *)malloc(sizeof(char) * 1024);
char c;
int column = 0;
int line = 0;
*result = NULL;
/* for each characters in the file */
while (read(fd, &c, 1) > 0) {
/* check for end of line */
if (c != '\n' && c != 0 && column < 1024 - 1)
buffer[column++] = c;
else {
/* string are null terminated in C */
buffer[column] = 0;
column = 0;
/* alloc memory for this line in result */
*result = (char **)realloc(*result, sizeof(char *) *
(line + 1));
/* duplicate buffer and store it in result */
(*result)[line++] = strdup(buffer);
}
}
free(buffer);
return line;
}
int main(int argc, char *argv[])
{
if (argc != 2) {
fprintf(stderr, "usage: %s [filename]", argv[0]);
return 1;
}
char **lines;
int line_count = read_file(argv[1], &lines);
if (line_count < 0) {
fprintf(stderr, "cannot open file %s\n", argv[1]);
return 1;
}
for(int i=0; i < line_count; i++)
printf("%s\n", lines[i]);
return 0;
}
Here an other version:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int read_file(const char *filename, char ***result)
{
/* init result */
*result = NULL;
/* open the file */
FILE *file = fopen(filename, "r");
if (file == NULL)
return -1;
/* read the file line by line */
char *buffer = (char *)malloc(sizeof(char) * 1024);
int line = 0;
while (fgets(buffer, 1024, file)) {
*result = (char **)realloc(*result, sizeof(char *) *
(line + 1));
(*result)[line++] = strdup(buffer);
}
free(buffer);
return line;
}
int main(int argc, char *argv[])
{
if (argc != 2) {
fprintf(stderr, "usage: %s [filename]", argv[0]);
return 1;
}
char **lines;
int line_count = read_file(argv[1], &lines);
if (line_count < 0) {
fprintf(stderr, "cannot open file %s\n", argv[1]);
return 1;
}
for(int i=0; i < line_count; i++)
printf("%s\n", lines[i]);
return 0;
}
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 am trying to read a file. I want to read each line from the file and check if there are any spelling error in that line.
For that I have added condition that data from file will store in buffer until it gets a new line characher '\n'. And after getting this line I want to empty the buffer and re insert the values in that.
Code I am using for the same is as follows:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#define W_COUNT 23800
#define MAX_LEN 100
char *dict[W_COUNT];
char buffer[MAX_LEN];
int num_words; //No of Words
char *statement[W_COUNT];
char buffer1[MAX_LEN];
void read_dictionary();
void file_read(char *);
void spell_check();
int word_search(char*);
int main(int argc, char*argv[]){
int i;
if(argc < 2){
printf("Expected Filename.\n");
exit(0);
}
read_dictionary();
file_read(argv[1]);
// spell_check();
}
void read_dictionary(){
FILE *fd;
int i = 0;
fd = fopen("dictionary", "r");
while ( fscanf(fd,"%s",buffer) != EOF)
dict[i++] = strdup(buffer);
num_words = i;
fclose(fd);
}
void file_read(char *filename){
FILE *fd;
int i = 0;
char c;
fd = fopen(filename,"r");
/*while ( fscanf(fd,"%s",buffer1) != EOF)
{
word[i++] = strdup(buffer1);
printf("File : %s\n", buffer1);
}*/
while ( ( c = fgetc(fd)) != EOF )
{
buffer1[i++] = tolower(c);
if ( c == '\n')
{
//printf("New Line\n");
spell_check();
buffer1[i] = 0;
}
//buffer1[i] = 0;
}
printf("Statement : %s\n", buffer1);
fclose(fd);
}
void spell_check(){
char *str;
str = strtok(buffer1," .?,!-");
while( str != NULL){
if(!word_search(str))
printf("%s Not found.\n",str);
str = strtok(0," .?,!-");
}
}
int word_search(char *word){
int high, low, mid;
high = num_words - 1;
low = 0;
int found = 0;
while (found == 0){
mid = (low + high) / 2;
if(strcmp(word, dict[mid]) == 0)
return 1;
else if(strcmp(word,dict[mid]) < 0)
high = mid - 1;
else
low = mid + 1;
if ( low > high)
return 0;
}
}
Any suggestions will be appreciated.
Thank you in advance.
while ( ( c = fgetc(fd)) != EOF )
{
buffer1[i++] = tolower(c);
if ( c == '\n')
{
//printf("New Line\n");
spell_check();
i = 0;
buffer1[i] = 0;
}
//buffer1[i] = 0;
}
For each line reading you have to assign the 0 to the i. After that you have to assign the null to the 0th position in the buffer.
You can try the above code for loop it will work.
I am currently collecting input from a file but my program separates each letter into the char array instead of each word. How can I change my code to get each word?
char c, fileName[20];
FILE *f;
void getFile() {
f = fopen(fileName, "r");
while((c = fgetc(f)) != EOF) {
printf("%c",c);
}
fclose(f);
}
You can use a scanset with fscanf or sscanf. This scanset, %29[a-zA-Z], reads lower and upper case English characters and stops when it encounters a character not in the set. The 29 limits the maximum number of characters to read so as to not overwrite the buffer, word[30]. When fscanf fails, the else will read one character from the file and give fscanf another try at reading another word.
This also uses the command line to pass in the file to read as argv[1].
#include <stdio.h>
#include <stdlib.h>
int main( int argc, char *argv[])
{
char word[30] = {'\0'};
int ch = 0;
FILE *pf = NULL;
if ( argc != 2) {//command requires program name and a file name
printf ( "useage: program filename\n");
return 1;
}
if ( ( pf = fopen ( argv[1], "r")) == NULL) {
perror ( "could not open file");
return 1;
}
while ( 1) {
if ( ( fscanf ( pf, "%29[a-zA-Z]", word)) == 1) {
printf ( "%s\n", word);
}
else {
if ( ( ch = fgetc ( pf)) == EOF) {//read one character and check for end of file
break;
}
//could do something here with the value of ch if needed
}
}
printf ( "--DONE--\n");
return 0;
}
This will allocate an array for each word. As words are added the array is expanded using realloc.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main( int argc, char *argv[])
{
char **words = NULL;//pointer for words
char **temp = NULL;
char word[30] = {'\0'};
int ch = 0;
int each = 0;
int found = 0;
int count = 0;
int wordsize = 0;
FILE *pf = NULL;
if ( argc != 2) {//command requires program name and a file name
printf ( "useage: program filename\n");
return 1;
}
if ( ( pf = fopen ( argv[1], "r")) == NULL) {
perror ( "could not open file");
return 1;
}
while ( 1) {
if ( ( fscanf ( pf, "%29[a-zA-Z]", word)) == 1) {
found = 0;
for ( each = 0; each < wordsize; each++) {
if ( strcmp ( words[each], word) == 0) {
found = 1;
break;
}
}
if ( found == 0) {
wordsize += 1;// increment number of words
temp = realloc ( words, wordsize * sizeof ( char *));//reallocate for another word
if ( temp != NULL) {
words = temp;
words[wordsize - 1] = malloc ( strlen ( word) + 1);//malloc for the word itself
if ( words[wordsize - 1] != NULL) {
strcpy ( words[wordsize - 1], word);
}
else {
printf ( "malloc failed\n");
wordsize -= 1;
break;
}
}
else {
printf ( "realloc failed\n");
wordsize -= 1;
break;
}
}
printf ( "%s\n", word);
}
else {
if ( ( ch = fgetc ( pf)) == EOF) {//read one character and check for end of file
break;
}
//something could be done with ch if needed
}
}
printf ( "--DONE Reading file--\n");
for ( each = 0; each < wordsize; each++) {// print each word
printf ( "%s\n", words[each]);
}
count = 0;
printf ( "Enter a word to search for\n");
if ( ( scanf ( "%29[a-zA-Z]", word)) == 1) {
for ( each = 0; each < wordsize; each++) {
if ( strcmp ( words[each], word) == 0) {
printf ( "Found %s at index %d\n" word, each);
count++;
}
}
printf ( "Found %s %d times\n" word, count);
}
for ( each = 0; each < wordsize; each++) {//release memory
free ( words[each]);
}
free ( words);
return 0;
}
You could use char * fgets ( char * str, int num, FILE * stream );
Then use char *strtok(char *str, const char *delim)
for example
#include <stdio.h>
int main()
{
FILE * pFile;
char mystring [100];
const char delimters[2] = " ,:";
char *token;
pFile = fopen ("myfile.txt" , "r");
if (pFile == NULL) perror ("Error opening file");
else {
if ( fgets (mystring , 100 , pFile) != NULL )
/* get the first token */
token = strtok(mystring, delimiters);
/* walk through other tokens */
while( token != NULL )
{
printf( " %s\n", token );
token = strtok(NULL, delimiters);
}
fclose (pFile);
}
return 0;
}
Use fscanf(3) instead
char word[256], *p;
while(fscanf(f, "%s", &word) != EOF) {
printf("%s\n", word);
/* break down word into individual chars */
for(p=word; *p; p++) {
printf("%c ", *p);
}
printf("\n");
}
First problem fgetc() returns an int you cannot store EOF in a char variable.
You should check if fopen() didn't return NULL.
You can use this technique to read words like this
#include <stdlib.h>
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#define MAX_BUFFER_SIZE 256
char **load_words_from_file(const char *filename)
{
size_t wordcount;
size_t charcount;
char buffer[MAX_BUFFER_SIZE];
int chr;
FILE *file;
char **words;
void *pointer;
file = fopen(filename, "r");
if (file == NULL)
return NULL;
wordcount = 0;
charcount = 0;
words = NULL;
while ((chr = fgetc(file)) != EOF)
{
/* it's a white space or it exceeded buffer size, it's a word delimiter */
if ((isspace(chr) != 0) || (charcount >= sizeof(buffer) - 1))
{
/* 'nul' terminate 'buffer' for strcpy() and strlen() */
buffer[charcount] = '\0';
pointer = realloc(words, (1 + wordcount) * sizeof(char *));
if (pointer == NULL) /* failure, free allocated memory and return NULL */
goto failure;
words = pointer;
words[wordcount] = malloc(1 + charcount);
charcount = 0; /* reset character count */
if (words[wordcount] == NULL)
goto failure;
strcpy(words[wordcount], buffer);
wordcount += 1;
}
else
{
/* store the character and count it */
buffer[charcount] = (char)chr;
charcount += 1;
}
}
pointer = realloc(words, (1 + wordcount) * sizeof(char *));
if (pointer == NULL)
goto failure;
words = pointer;
words[wordcount] = NULL; /* this will let you know when to stop fetching words */
fclose(file);
return words;
failure:
for (size_t i = 0 ; i < wordcount ; ++i)
free(words[i]);
free(words);
return NULL;
}
int
main()
{
const char *filename = "your-file-name-here";
char **words = load_words_from_file(filename);
size_t counter = 0;
if (words == NULL)
{
printf("no words found in the file\n");
return -1;
}
while (words[counter] != NULL)
{
printf("%zuth word: %s\n", 1 + counter, words[counter]);
free(words[counter]); /* this program will not use it again */
counter += 1;
}
free(words);
return 0;
}
the strtok() method would also work, but it's harder to understand.
Note the use of goto, it's a benign usage, although some people think that goto is always harmful, that's not true, using it like this makes the program adhere to the DRY priniciple.
I am working on a program that includes a selection of code which is "supposed" to filter a string in order to prevent non-alphanumeric characters (except for underscores) from being passed further on into the program. The part that does this worked fine when I tested it before implementing it in the main program (as shown below), but when I run it now the output is just repeated a bunch of times until there is a segmentation fault, and i cannot for the life of me figure out what is causing this to happen, so if anyone could help with this problem I would very much appreciate it, thanks! also for ease of seeing where this is implemented in the main program, i have taken a screenshot of where it is located in the main code http://i.imgur.com/dKLgx.png, and my apologies for the long post length
austin#Ruby:~/cprac$ ./words
[hel123_lo]
testing code that worked
#include <stdio.h>
#include <string.h>
#include <ctype.h>
int main(void) {
int i;
char *p;
char stg[] = "hel123*^_l!o";
char output[200] = {0x00};
int index = 0;
p = stg;
while( *p )
{
if (isalnum(*p) || *p == '_')
{
output[index++] = *p;
}
p++;
}
printf("[%s]\n", output);
return 0;
}
main code
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#ifndef max
#define max(a, b) ((a)>(b))? (a) : (b)
#endif
long GetFileSize(FILE *fp){
long fsize = 0;
fseek(fp,0,SEEK_END);
fsize = ftell(fp);
fseek(fp,0,SEEK_SET);//reset stream position!!
return fsize;
}
char *lastline(char *filepath){
FILE *fp;
char buff[4096+1];
int size,i;
long fsize;
if(NULL==(fp=fopen(filepath, "r"))){
perror("file cannot open at lastline");
return NULL;
}
fsize= -1L*GetFileSize(fp);
if(size=fseek(fp, max(fsize, -4096L), SEEK_END)){
perror("cannot seek");
exit(0);
}
size=fread(buff, sizeof(char), 4096, fp);
fclose(fp);
buff[size] = '\0';
i=size-1;
if(buff[i]=='\n'){
buff[i] = '\0';
}
while(i >=0 && buff[i] != '\n')
--i;
++i;
return strdup(&buff[i]);
}
int main(int argc, char *argv[], char *envp[]){
char *last;
char *name;
char field_x[128];
char field_y[128];
char field_z[128];
char field_world[128];
char field_cause[128];
char field_killer[128];
name = getenv("MCEXEC_PLAYERNAME");
char *filename;
char *p;
char *ispvp;
// m
int i;
char *f;
char output[200] = {0x00};
int index = 0;
filename = malloc(sizeof "/home/minecraft/freedonia/playerdata/deathlog-.txt" - 1 + strlen(name) + 1);
if (!filename) exit(EXIT_FAILURE);
snprintf(filename,4096,"/home/minecraft/freedonia/playerdata/deathlog- %s.txt",name);
last = lastline(filename);
if( last != NULL ) {
printf( "%s\n", last );
sscanf(last, "%*[^:]:%*[^:]:%*[^:]:%127[^:]:", field_x);
sscanf(last, "%*[^:]:%*[^:]:%*[^:]:%*[^:]:%127[^:]:", field_y);
sscanf(last, "%*[^:]:%*[^:]:%*[^:]:%*[^:]:%*[^:]:%127[^:]:", field_z);
sscanf(last, "%*[^:]:%*[^:]:%*[^:]:%*[^:]:%*[^:]:%*[^:]:%127[^:]:", field_world);
sscanf(last, "%*[^:]:%*[^:]:%*[^:]:%*[^:]:%*[^:]:%*[^:]:%*[^:]:%127[^:]:", field_cause);
p = strchr(field_cause, '_');
printf( "X coord: %s\n", field_x);
printf( "Y coord: %s\n", field_y);
printf( "Z coord: %s\n", field_z);
printf( "World: %s\n", field_world);
printf( "Cause: %s\n", field_cause);
while (p != NULL) {
ispvp = "true";
// printf ("found at %d\n",p - field_cause + 1);
sscanf(field_cause, "%*[^_]_%128[^_]_", field_killer);
printf( "%s\n", field_killer);
f = field_cause;
while( *f )
{
if (isalnum(*f) || *f == '_')
{
output[index++] = *f;
}
f++;
}
printf("[%s]\n", output);
// p = strchr(p + 1, '_');
}
}
// printf("\"%s\"\n", last);
free(last);
return 0;
}
while (p != NULL) {
ispvp = "true";
// printf ("found at %d\n",p - field_cause + 1);
sscanf(field_cause, "%*[^_]_%128[^_]_", field_killer);
printf( "%s\n", field_killer);
f = field_cause;
while( *f )
{
if (isalnum(*f) || *f == '_')
{
output[index++] = *f;
}
f++;
}
printf("[%s]\n", output);
// p = strchr(p + 1, '_');
}
P never changes in this block, so it will always be != NULL.