I am coding a program which takes a text file as an input, makes the index of the words of it and prints the output(the index) in a file and in the screen. I coded as below and tried much to spot the problem or at least narrow it down, but I couldn't. If anyone can help or spots a problem in syntax or the logic of the code, I would be happy to know.
void main(int argc, char * argv[])
{
//clearscreen
clrscr();
//if arguments are less that default of the program
if (argc < 2)
{
cout << "You should've input 3 arguments." ;
return;
}
//opening the input file and defining a pointer which points to it as argv[1]
FILE *fPtr = fopen(argv[1], "r+");
//defining a 2D array to hold maximum to 200 words holding maximum to 20 characters
char words[200][20];
//initializing words 2D array with zero ASCII
for(int i = 0; i < 200; i++)
for(int j = 0; j < 20; j++)
words[i][j] = 255;
//defining an 2D whi array which is supposed to show how many times words are placed in which lines in a defined layout
//it holds maximum to 200 words holding maximum 100 sentences
int index[200][100];
//initializing the index 2D array with zero ASCII
for(i = 0; i < 200; i++)
for(j = 0; j < 100; j++)
index[i][j] = 0;
//this array of characters max to 2000 is supposed to hold each line which is gotten with fgets
char buff[2000];
//initializing the buff array with zero ASCII
for(i = 0; i < 2000; i++)
buff[i] = 0;
//the max of the words used in the source file is 200. but this valuable named as 'last' says how many words are used in this source file
//its initalized as no words is held
int last = 0;
//defining a pointer to char of punctuation mark characters. all ASCII codes expect for a - z, A - Z, 0 - 9 and newline
char *punc;
//initializing punctuation marks array
for(i = 0; i < 256; i++)
{
if(i == 10)
continue;
if(i >= '0' && i <= '9')
continue;
if(i >= 'a' && i <= 'z')
continue;
if(i >= 'A' && i <= 'Z')
continue;
char *string = (char *) &i;
strncat(punc, string, 1);
}
//how many lines is read from the source file
int lineread = 0;
//a word which the processes are done on that
char *word;
//one line read
while( fgets(buff, 1999, fPtr) != NULL)
{
//how many words is read from the source file in the current line
int wordread = 0;
word = strtok(buff, punc);
//one word read
while( word != NULL)
{
//sorting
int k = 0;
while(strcmp(word, words[k])> 0)
k++;
if(strcmp(word, words[k]))
{
for(int l = last; l >= 0; l--)
{
strcpy(words[l + 1],words[l]);
for(int o = 0; o <= lineread; o++)
index[l + 1][o] = index[l][o];
}
last++;
strcpy(words[k],word);
for(l = 0; l <= lineread; l++)
index[k][l] = 0;
}
index[k][lineread]++;
wordread++;//go to next word
word = strtok(NULL, punc);
}
lineread++;//go to next line
}
//closing the input file
fclose(fPtr);
//opening the output file and defining a pointer which points to it as argv[2]
FILE *fPtr2 = fopen(argv[2], "w+");
//showing the index in cmd
for(i = 0; i <= last; i++)
{
printf("%-20s" , words[i]);
fprinf(fPtr2, "%-20s" , words[i]);
int m = 0;
for(j = 0; j <= lineread; j++)
{
if(m)
{
printf("%c", ',');
fprintf(fPtr2, "%c", ',');
}
if(index[i][j])
{
printf("%i", j + 1);
fprintf(fPtr2, "%i" ,j + 1);
}
if(index[i][j] > 1)
{
printf("(%i)", index[i][j]);
fprintf(fPtr2, "(%i)", index[i][j]);
m = 1;
}
}
printf("\n");
fprintf(fPtr2, "\n");
}
//closing the output file
fclose(fPtr);
}
now it errors as Abnormal program termination NULL pointer assignment. I have to use turbo c and I use DOS SHELL. there's a file names as "input.txt" in resourse. and in DOS SHELL I write this:
programname.exe input.txt output.txt
and my desired output if input.txt is this:
hello. hello.
how are
you? hello.
desired output:
hello 1(2),3 //2 times in line 2, 1 time in line 1
how 2 //1 time in line 2
are 2 //1 time in line 2
you 3 //1 time in line 3
the problem is with this line:
while(strcmp(word, words[k])> 0)
Because index is initialized as 255 and according to the algorithm strcmp works based on, for first word the code works right and puts it in word[0] but for the second word it won't work properly.for example:
first word: Kittens
second word: Biscuits
first strcmp compares Kittens with 255 ASCII code. the result is that Kitten is smaller and the process will put it in word[0]. But for the second word, strcmp compares Biscuits with Kittens and the result is that Kittens is bigger and program will go through another blocks of word[] which in not wanted. the program will be fixed by initializing word[] to 0 and using this code instead of that which is first mentioned:
while(strcmp(word, words[k])> 0)
Related
I am trying to build a program that parses an array of chars from input and then returns a formatted omitting extra whites spaces.
#include <stdio.h>
# include <ctype.h>
/* count charecters in input; 1st version */
int main(void)
{
int ch, outp=0;
char str[1000], nstr[1000];
/* collect the data string */
while ((ch = getchar()) != EOF && outp < 1000){
str[outp] = ch;
outp++;
}
for (int j = 0; j < outp-1; j++){
printf("%c",str[j]);
}
printf("\n");
for (int q = 0; q < outp-1; q++)
{
if (isalpha(str[q]) && isspace(str[q+1])){
for(int i = 0; i < outp; i++){
if (isspace(str[i]) && isspace(i+1)){
continue;
}
nstr[i] = str[i];
}
}
}
printf("\n");
printf("Formated Text: ");
for (int i = 0; i < outp-1; i++){
printf("%c", nstr[i]);
}
//putchar("\n");c
// printf("1");
return 0;
}
Here is my code. The array is never fully parsed, the end is usually omitted, odd chars show up and past attempts have yielded a not fully parsed array, Why?
This is exercise 1-9 from "the C programming language".
a) You need to use an additional index variable while copying the characters from str to nstr. Do something like -
for(int i = 0, j = 0; i < outp -1; i++){
if (isspace(str[i]) && isspace(i+1)){
continue;
}
nstr[j++] = str[i];
}
b) While you are printing nstr, you are using the length of the original string str. The length of nstr will be less than that of str since you have removed the spaces.
You need to find the length of nstr now or use i < strlen(nstr) -1 in the condition.
int read_word(char word[], int max_size_word) {
{
int c = 0, let_count = 0;
printf("\nPlease enter your word: ");
char input = toupper(getchar());
for(c = 1; c < 7; c++) {
if(input != '\n') {
word[c] = input;
let_count++;
} else if(input == '\n')
input = toupper(getchar()); //The word the user entered is in word[c]
}
return let_count;
}
}
int check_word(char word[], int size_word, int letter_set[], int
size_letter_set, int arr[])
{
char word_copy;
for(int ii = 0; ii < 7; ii++) {
word_copy = word[ii];
}
printf("The word is %c\n" , word_copy);
return 0;
}
I'm programming a game of scrabble. Here are the two functions that pertain to my question. Basically I want to check if my read word function works. Thats what the bottom printf does. However when I enter a couple letters my "The word is...." printf only gives back the first letter entered. I want the printf to give back every letter entered. Any help would be appreciated!
You're only printing one letter because in printf("The word is %c\n" , word_copy); your word_copy is a char and not a string.
In check_word, try replacing
char word_copy;
for(int ii = 0; ii < 7; ii++) {
word_copy = word[ii];
}
printf("The word is %c\n" , word_copy);
return 0;
by
int word_size = strlen(word); //calculate the length of your word
char word_copy[word_size + 1]; //create copy string with word size +1 for \0
int ii = 0;
for(ii; ii < 7; ii++) { //I set ii < 7 to do like you but... Why did you set 7?
word_copy[ii] = word[ii]; //put the characters of your word into the copy string
}
word_copy[ii] = '\0'; //end the string puttin a \0 at its end
printf("The word is %s\n" , word_copy); //here i replace %c (char) by %s (string)
return 0;
There are similar problems in your read_word function, you should be able to fix them if you understand the fixes I made in your check_word function (even if you can just put your printf in the for loop i think that doing it like so can help you understand the problem in read_word).
I'm trying to make a program that translates words that are in a file and puts them in another file. Here I'm trying to read the words and put them into an array so I can search for them later and then print back into another file the translated word.
For the moment I'm trying to read and print from the array:
#include<stdio.h>
#include <string.h>
int main()
{
char rom_eng[4][2], fran_eng[4][2];
int i, j;
FILE* re = fopen("rom_eng.txt", "r");
FILE* out = fopen("out.txt", "w");
if (re == NULL)
{
printf("Error");
return 1;
}
for (i = 0; i < 2; i++)
{
for (j = 0; j < 4; j++)
fscanf(re, "%s", &rom_eng);
}
for (i = 0; i < 2; i++)
{
for (j = 0; j < 4; j++)
fprintf(out, "%s \n", rom_eng);
}
return 0;
}
The words in the file are like this:
- word word
- word word
The output is the same last word repeatedly printed in the out file.
You define : char rom_eng[4][2], fran_eng[4][2];
And then you read: fscanf(re, "%s", &rom_eng);
You 're not supposed to put the '&' before rom_eng because it is defined as a char, and chars are already pointers to adresses, so in this case you dont need to put the '&' to point to the adress.
My assignment is to allow the user to enter any input and print the occurrences of letters and words, we also have to print out how many one letter, two, three, etc.. letter words are in the string. I have gotten the letter part of my code to work and have revised my word function several times, but still can't get the word finding function to even begin to work. The compiler says the char pointer word is undeclared when it clearly is. Do I have to allocate memory to it and the array of characters?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void findLetters(char *ptr);
void findWords(char *point);
int main()
{
char textStream[100]; //up to 98 characters and '\n\ and '\0'
printf("enter some text\n");
if (fgets(textStream, sizeof (textStream), stdin)) //input up to 99 characters
{
findLetters(textStream);
findWords(textStream);
}
else
{
printf("fgets failed\n");
}
return 0;
}
void findLetters(char *ptr) //find occurences of all letters
{
int upLetters[26];
int loLetters[26];
int i;
int index;
for (i = 0; i < 26; i++) // set array to all zero
{
upLetters[i] = 0;
loLetters[i] = 0;
}
i = 0;
while (ptr[i] != '\0') // loop until prt[i] is '\0'
{
if (ptr[i] >= 'A' && ptr[i] <= 'Z') //stores occurrences of uppercase letters
{
index = ptr[i] - 'A';// subtract 'A' to get index 0-25
upLetters[index]++;//add one
}
if (ptr[i] >= 'a' && ptr[i] <= 'z') //stores occurrences of lowercase letters
{
index = ptr[i] - 'a';//subtract 'a' to get index 0-25
loLetters[index]++;//add one
}
i++;//next character in ptr
}
printf("Number of Occurrences of Uppercase letters\n\n");
for (i = 0; i < 26; i++)//loop through 0 to 25
{
if (upLetters[i] > 0)
{
printf("%c : \t%d\n", (char)(i + 'A'), upLetters[i]);
// add 'A' to go from an index back to a character
}
}
printf("\n");
printf("Number of Occurrences of Lowercase letters\n\n");
for (i = 0; i < 26; i++)
{
if (loLetters[i] > 0)
{
printf("%c : \t%d\n", (char)(i + 'a'), loLetters[i]);
// add 'a' to go back from an index to a character
}
}
printf("\n");
}
void findWords(char *point)
{
int i = 0;
int k = 0;
int count = 0;
int j = 0;
int space = 0;
int c = 0;
char *word[50];
char word1[50][100];
char* delim = "{ } . , ( ) ";
for (i = 0; i< sizeof(point); i++) //counts # of spaces between words
{
if ((point[i] == ' ') || (point[i] == ',') || (point[i] == '.'))
{
space++;
}
}
char *words = strtok(point, delim);
for(;k <= space; k++)
{
word[k] = malloc((words+1) * sizeof(*words));
}
while (words != NULL)
{
printf("%s\n",words);
strcpy(words, word[j++]);
words = strtok(NULL, delim);
}
free(words);
}
This is because you are trying to multiply the pointer position+1 by the size of pointer. Change line 100 to:
word[k] = malloc(strlen(words)+1);
This will solve your compilation problem, but you still have other problems.
You've got a couple of problems in function findWords:
Here,
for (i = 0; i< sizeof(point); i++)
sizeof(point) is the same as sizeof(char*) as point in a char* in the function fincdWords. This is not what you want. Use
for (i = 0; i < strlen(point); i++)
instead. But this might be slow as strlen will be called in every iteration. So I suggest
int len = strlen(point);
for (i = 0; i < len; i++)
The same problem lies here too:
word[k] = malloc((words+1) * sizeof(*words));
It doesn't makes sense what you are trying with (words+1). I think you want
word[k] = malloc( strlen(words) + 1 ); //+1 for the NUL-terminator
You got the arguments all mixed up:
strcpy(words, word[j++]);
You actually wanted
strcpy(word[j++], words);
which copies the contents of words to word[j++].
Here:
free(words);
words was never allocated memory. Since you free a pointer that has not been returned by malloc/calloc/realloc, the code exhibits Undefined Behavior. So, remove that.
You allocated memory for each element of word. So free it using
for(k = 0; k <= space; k++)
{
free(word[k]);
}
Your calculation of the pointer position+1 is wrong. If you want the compilation problem will go away change line 100 to:
word[k] = malloc( 1 + strlen(words));
I have rjecnik.txt file that looks like this
mate sime, jure
stipica gujo, prvi
ante mirkec
goran maja, majica
avion kuca, brod, seoce
amerika, neka, zemlja, krcma
brodarica, zgrada, zagreb
zagreb split
zadar rijeka
andaluzija azija
I need to order lines alphabetically (not words) and my program produces this result which is not correct:
andaluzija azijamate sime, jure
amerika, neka, zemlja, krcma
brodarica, zgrada, zagreb
ante mirkec
avion kuca, brod, seoce
goran maja, majica
stipica gujo, prvi
zadar rijeka
zagreb split
Press [Enter] to close the terminal ...
When I use non ascii character like kuća for kuca or krčma for krcma it produces this result (all wrong)
andaluzija azijamate sime, jure
amerika, neka, zemlja, krŔma
brodarica, zgrada, zagreb
ante mirkec
avion kuŠa, brod, seoce
goran maja, majica
stipica gujo, prvi
zadar rijeka
zagreb split
Press [Enter] to close the terminal ...
This is my code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
int ch, nl = 1, min, lenght1, lenght2, lenght;//ch will hold characters, min is for selection sort, lenght holds value of strlen for determine wthat line is longer
FILE * fp;// FILE pointer
char * lines[1000];//that will dynamically hold strings for lines
char * temp;//for lines swaping
if((fp = fopen("C:\\Users\\don\\Documents\\NetBeansProjects\\proba2\\dist\\Debug\\MinGW-Windows\\rjecnik.txt", "r")) == NULL)//I had to temporarily put full path to rjecnik.txt
{
printf("Can't open file...");
exit(1);
}
while((ch = getc(fp)) != EOF)//count lines
{
if(ch == '\n')
nl++;
}
int i, j;
for (i = 0; i < nl; i++)
lines[i] = malloc(1000);//create array of string size value of nl
fseek(fp, 0L, SEEK_SET);//go to start of file
i = 0;
j = 0;
while((ch = getc(fp)) != EOF)//fill arrays of string
{
lines[i][j] = ch;
j++;
if(ch == '\n')
{
j = 0;
i++;
}
}
for(i = 0; i < nl - 1; i++)//selection sort doesn't work properly
{
min = i;//min is i
for(j = i + 1; j < nl; j++)//for number of lines(nl) times
{
lenght1 = strlen(lines[i]);//find what string is longer and lenght is smaller one
lenght2 = strlen(lines[j]);
if(lenght1 < lenght2)
lenght = lenght1;
else
lenght = lenght2;
if(strncmp(lines[i], lines[j], lenght) > 0 )//compare two strings
min = j;//if second string is alphabetically smaller min is j
}
temp = lines[i];// swapping
lines[i] = lines[min];
lines[min] = temp;
}
for(i = 0; i < nl; i++ )//printing to console
{
lenght1 = strlen(lines[i]);
for(j = 0; j < lenght1; j++ )
{
putchar(lines[i][j]);
}
}
return 0;
}
Now program crashes at the end when I add this code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
int ch, nl = 1, min, lenght1, lenght2, lenght;//ch will hold characters, min is for selection sort, lenght holds value of strlen for determine wthat line is longer
FILE * fp;// FILE pointer
char * lines[1000];//that will dynamically hold strings for lines
char * temp;//for lines swaping
if((fp = fopen("C:\\Users\\don\\Documents\\NetBeansProjects\\proba2\\dist\\Debug\\MinGW-Windows\\rjecnik.txt", "r")) == NULL)//I had to temporarily put full path to rjecnik.txt
{
printf("Can't open file...");
exit(1);
}
while((ch = getc(fp)) != EOF)//count lines
{
if(ch == '\n')
nl++;
}
int i, j;
for (i = 0; i < nl; i++)
lines[i] = malloc(1000);//create array of string size value of nl
fseek(fp, 0L, SEEK_SET);//go to start of file
i = 0;
j = 0;
while((ch = getc(fp)) != EOF)//fill arrays of string
{
lines[i][j] = ch;
j++;
if(ch == '\n')
{
j = 0;
i++;
}
}
for(i = 0; i < nl - 1; i++)//selection sort doesn't work properly
{
min = i;//min is i
for(j = i + 1; j < nl; j++)//for number of lines(nl) times
{
lenght1 = strlen(lines[i]);//find what string is longer and lenght is smaller one
lenght2 = strlen(lines[j]);
if(lenght1 < lenght2)
lenght = lenght1;
else
lenght = lenght2;
if(strncmp(lines[min], lines[j], lenght ) > 0 )//compare two strings
min = j;//if second string is alphabetically smaller min is j
}
temp = lines[i];// swapping
lines[i] = lines[min];
lines[min] = temp;
}
for(i = 0; i < nl; i++ )//printing to console
{
lenght1 = strlen(lines[i]);
for(j = 0; j < lenght1; j++ )
{
putchar(lines[i][j]);
}
}
for (i = 0; i < 100; i++)//Program crashes here
free(lines[i]);
return 0;
}
1.- You must initialize lines to 0 after malloc so strlen works properly.
2.- Compare lines[j] with lines[min]
3.- Don't forget free lines
You're always comparing lines[j] to lines[i], but you should be comparing it to lines[min].
If this isn't you learning about how to sort and get input, c provides qsort() and fgets(), so you could
int strsort(const void *a, const void *b)
{
char *const*astr=a, *const*bstr=b;
return strcmp(*astr, *bstr);
}
main()
{
FILE*f = fopen(...);
char (*arr)[1000] = malloc(1000*1000);
int x;
for(x=0;x<1000 && fgets(1000, arr[x], f);x++)
arr[x][strlen(arr[x])-2] = '\0'; //strip newlines
qsort(arr, x, 1, strsort);
int i;
for(i=0; i<x; i++)
printf("%s\n", arr[x]);
}
It's much clearer what you're doing this way.
Minor nitpick:
lenght1 = strlen(lines[i]);
lenght2 = strlen(lines[j]);
if(lenght1 < lenght2)
lenght = lenght1;
else
lenght = lenght2;
if(strncmp(lines[i], lines[j], lenght) > 0 )
... ;
You don't need this: strcmp() stops when either of the strings terminates, whichever comes first. In your case, you need to compare one more character (the NUL), like
strncmp( lines[i], lines[j], lenght+1)
, otherwise "apple" and "apples" would compare equal (because only the first five characters would be compared). But the "normal" form:
strcmp(lines[i], lines[j])
does exactly what you want.