String Check not returning a value - c

Program should read in any input a user desires (in this case just a string of a’s and b’s) ended by an “*”, then it prompts the user for the substring they wish to search for (in this case “baab”). If the substring is found then the program indicates a yes, no if its not found. I was not allowed to use built in matching utilities and it has to read one character at a time.
I just replaced gets() with a scanf, now when i type in my substring and im sure its a match it still says no?
#include<stdio.h>
#include<string.h>
int search(char[], char[]);
int main()
{
char a[100], b[40];
int loc;
printf("Enter the main string :");
scanf("%s", a);
printf("Enter the search string :");
scanf("%s", b);
loc = search(a, b);
if (loc == -1)
printf("No");
else
printf("Yes %d", loc + 1);
return (0);
}
int search(char a[], char b[])
{
int i, j, firstOcc;
i = 0, j = 0;
while (a[i] != '*')
{
while (a[i] != b[0] && a[i] != '*')
i++;
if (a[i] == '*')
return (-1);
firstOcc = i;
while (a[i] == b[j] && a[i] != '*' && b[j] != '*')
{
i++;
j++;
}
if (b[j] == '*')
return (firstOcc);
if (a[i] == '*')
return (-1);
i = firstOcc + 1;
j = 0;
}
}

You need to terminate the second string with a * as well - then things match properly. As it is, your code keeps matching "one character too much" - and it finds the '\0' at the end of the b string which doesn't match.
If you don't want to have an asterisk at the end of your b string, you must not write code that expects it... You could modify your code as follows (I put in ample printf statements so you can see what is going on). Note - I left the fix to gets in as an exercise. Really, please. Fix it.
include <stdio.h>
int search(char a[], char b[]);
int main()
{
char a[100], b[40];
int loc;
printf("Enter the main string terminated with '*':");
gets(a); // please don't...
printf("Enter the search string :");
gets(b);
loc = search(a, b);
if (loc == -1)
printf("No");
else
printf("Yes %d", loc + 1);
return (0);
}
int search(char a[], char b[])
{
int i = 0, j = 0, lenB, firstOcc;
for(lenB=0; b[lenB]!='\0';lenB++);
printf("a is %s\n", a);
while (a[i] != '*')
{
printf("i = %d\n", i);
while (a[i] != b[0] && a[i] != '*')
i++;
if (a[i] == '*')
return (-1);
printf("matching a[i]=%c and b[0]=%c\n", a[i], b[0]);
firstOcc = i;
while (a[i] == b[j] && a[i] != '*' && j < lenB)
{
printf("a[%d] matches b[%d]\n", i, j);
i++;
j++;
}
if (j == lenB)
return (firstOcc);
if (a[i] == '*')
return (-1);
i = firstOcc + 1;
j = 0;
printf("going to take another look with i=%d and j=%d\n", i, j);
}
}

Related

Why does i never get past 1?

I am trying to create a program to solve a wordsearch from a 2D array using only pointers. In my primary function for doing the actual search for the words I have a while loop that is supposed to keep going as long as i doesn't exceed the length of the word and as long as the letters from the word correspond to the letters on the grid. After finding the word it should make the letters on the grid lowercase and print out that it found the word. Here is my entire program right now.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
void printPuzzle(char** arr, int n);
void searchPuzzle(char** arr, int n, char** list, int listSize);
void searchWord(int j, int k, int gridsize, char** arr, char** list, int listPos);
int main(int argc, char **argv) {
int bSize = 15;
if (argc != 2) {
fprintf(stderr, "Usage: %s <puzzle file name>\n", argv[0]);
return 2;
}
int i, j;
FILE *fptr;
char **block = (char**)malloc(bSize * sizeof(char*));
char **words = (char**)malloc(50 * sizeof(char*));
fptr = fopen(argv[1], "r");
if (fptr == NULL) {
printf("Cannot Open Puzzle File!\n");
return 0;
}
for(i=0; i<bSize; i++){
*(block+i) = (char*)malloc(bSize * sizeof(char));
fscanf(fptr, "%c %c %c %c %c %c %c %c %c %c %c %c %c %c %c\n", *(block+i), *(block+i)+1, *(block+i)+2, *(block+i)+3, *(block+i)+4, *(block+i)+5, *(block+i)+6, *(block+i)+7, *(block+i)+8, *(block+i)+9, *(block+i)+10, *(block+i)+11, *(block+i)+12, *(block+i)+13, *(block+i)+14 );
}
fclose(fptr);
fptr = fopen("states.txt", "r");
if (fptr == NULL) {
printf("Cannot Open Words File!\n");
return 0;
}
for(i=0; i<50; i++){
*(words+i) = (char*)malloc(20 * sizeof(char));
fgets(*(words+i), 20, fptr);
}
for(i=0; i<49; i++){
*(*(words+i) + strlen(*(words+i))-2) = '\0';
}
printf("Printing list of words:\n");
for(i=0; i<50; i++){
printf("%s\n", *(words + i));
}
printf("\n");
printf("Printing puzzle before search:\n");
printPuzzle(block, bSize);
printf("\n");
searchPuzzle(block, bSize, words, 50);
printf("\n");
printf("Printing puzzle after search:\n");
printPuzzle(block, bSize);
printf("\n");
return 0;
}
void printPuzzle(char** arr, int n){
for(int i = 0; i < n; i++){
printf("\n");
for(int j = 0; j < 15; j++){
printf("%c ", *(*(arr+i)+j));
}
}
}
void searchPuzzle(char** arr, int n, char** list, int listSize){
for(int i = 0; i < listSize; i++){
for(int j = 0; j < 15; j++){
for(int k = 0; k < 15; k++){
searchWord(j, k, 15, arr, list, i);
}
}
}
}
void searchWord(int j, int k, int gridsize, char** arr, char** list, int listPos){
int wordlength = strlen(*(list+listPos));
if(j+wordlength <= gridsize){ //Horizontal
int i = 0;
while(i < wordlength && *(*(arr+(j+i))+k) == *(*(list+listPos)+i)){
i++;
}
if(i == wordlength){
while(i > 0 && *(*(arr+(j+i))+k) == *(*(list+listPos)+i)){
*(*(arr+(j+i))+k) = tolower(*(*(arr+(j+i))+k));
i--;
}
printf("Word found: ");
for(i = 0; i < wordlength; i++)
printf("%c", *(*(list+listPos)+i));
}
}
if(k+wordlength <= gridsize){ //Vertical
int i = 0;
while(i < wordlength && *(*(arr+j)+(k+i)) == *(*(list+listPos)+i)){
i++;
}
if(i == wordlength){
while(i > 0 && *(*(arr+j)+(k+i)) == *(*(list+listPos)+i)){
*(*(arr+(j+i))+k) = tolower(*(*(arr+(j+i))+k));
i--;
}
printf("Word found: ");
for(i = 0; i < wordlength; i++){
printf("%c", *(*(list+listPos)+i));
}
}
}
if(j+wordlength <= gridsize && k+wordlength <= gridsize){ //Diagonal
int i = 0;
while(i < wordlength && *(*(arr+(j+i))+k) == *(*(list+listPos)+i)){
i++;
}
if(i == wordlength){
while(i > 0 && *(*(arr+(j+i))+(k+i)) == *(*(list+listPos)+i)){
*(*(arr+(j+i))+(k+i)) = tolower(*(*(arr+(j+i))+(k+i)));
i--;
}
printf("Word found: ");
for(i = 0; i < wordlength; i++)
printf("%c", *(*(list+listPos)+i));
}
}
}
This is the part I believe there is a problem with.
while(i < wordlength && *(*(arr+(j+i))+k) == *(*(list+listPos)+i)){
i++;
}
If I print out the decimal value of i after this while loop it should at some point approach the length of one of the words as I know some words are horizontal, however every time it loops through and prints the value of i it never exceeds 1 which means the while loop never runs more than once which is impossible with the wordsearch files I am using to test this. What is causing this to happen? It is also 0 or 1 for every other direction when I try, the example above was just the while loop from the horizontal search.
There may also be a problem with the function searchPuzzle and the amount it loops through. However, I think that may be just my imagination.
Additional Info: The grid is 15x15 and there are 50 words in the list.
I think that you might need to declare Wordsearch again after the && -
while(i < wordlength && wordlength *(*(arr+(j+i))+k) == *(*(list+listPos)+i)){
i++;
}

Trying to remove substring from string in C, keep failing

I know this question has been asked many times before but I simply cannot get my head around what I am doing wrong. Everytime I make some progress I get a new error. The code I am using is really basic because I am a newbie and our professor requires the usage of scanf and gets. This is my code so far:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_SIZE 100
int identify(char[], char[]);
int remove(char[], char[], int);
int scan(choice)
{
while(choice < 0 || choice > 7)
{
printf("Invalid input, choose again\n");
scanf("%d", &choice);
}
return choice;
}
int main()
{
char sentence[MAX_SIZE], word[MAX_SIZE];
int choice, i, j, k, deikths;
printf("Choose one of the following:\n");
printf("1. Give sentence\n");
printf("2. Subtract a word\n");
printf("3. Add a word\n");
printf("4. Count the words\n");
printf("5. Count the sentences\n");
printf("6. Count the characters\n");
printf("7. Is the phrase a palindrome?\n");
printf("0. Exit\n");
scanf("%d", &choice);
if(scan(choice) == 1)
{
printf("Give sentence:\n");
gets(sentence);
gets(sentence);
printf("%s\n", sentence);
}
else(scan(choice) == 2);
{
printf("Give word you want to subtract\n");
gets(word);
printf("%s", word);
deikths = identify(sentence, word);
if(deikths != -1)
{
remove(sentence, word, deikths);
printf("Sentence without word: %s\n", sentence);
}
else
{
printf("Word not found in sentence.\n");
}
}
}
int identify(char sentence[], char word[])
{
int i, j, k;
for(k = 0; word[k] != '\0'; k++);
{
for(i = 0, j = 0; sentence[i] != '\0'; i++)
{
if(sentence[i] == word[j])
{
j++;
}
else
{
j = 0;
}
}
}
if(j == 1)
{
return(i - j);
}
else
{
return -1;
}
}
int remove(char sentence[], char word[], int deikths)
{
int i, k;
for(k = 0; word[k] != '\0'; k++)
{
for(i = deikths; sentence[i] != '\0'; i++)
{
sentence[i] = sentence[i + k + 1];
}
}
}
The error I am getting, is that the remove function has conflicting types. Any help with fixing my code will be greatly appreciated, or even an alternative solution to my problem would bre great.
As established in the comments, the compiler error is generated because remove is already defined in the stdio.h. After changing, the name the code compiles successfully, but still doesn't work as expected.
identify is the function which is meant to find whether a substring exists in a string and return its position. This is very similar to how strstr from the standard library works - I'd suggest having a look at an implementation of that function, to better understand how this is done.
The function you implemented only correctly finds substrings of length 1, at the end of the string. I have highlighted errors in the code below which cause this.
int identify(char sentence[], char word[])
{
int i, j, k;
for(k = 0; word[k] != '\0'; k++); // <- this loops is never actually ran because of the trailing semicolon - this is however a good thing as it is redundant
{
for(i = 0, j = 0; sentence[i] != '\0'; i++)
{
if(sentence[i] == word[j])
{
j++;
}
else
{
j = 0; // <- this makes it so only matches at the end can be found - otherwise, j is just reset back to 0
}
}
}
if(j == 1) // <- this makes it so only matches of length 1 can be found
{
return(i - j); // <- this is only correct if the match is at the end of the sentence
}
else
{
return -1;
}
}
strremove is inefficient due to the nested loops and the range of characters copied needs to be shortened - right now data is access beyond the end of the array.
int strremove(char sentence[], char word[], int deikths)
{
int i, k;
for(k = 0; word[k] != '\0'; k++) // <- this loop is redundant
{
for(i = deikths; sentence[i] != '\0'; i++) // <- you need to add range checking to make sure sentence[i+k+1] doesn't go beyond the end of the string
{
sentence[i] = sentence[i + k + 1];
}
}
}
I will leave the problems in main as an exercise to you - this is an assignment after all.

Writing(in a file) and printing statistics

My task is to create a C program that opens a .c file in which the user then writes some text then said text is printed along with the number of (){}/ and the percentage ratio comments:whole text of the C program.
So far I've this:
#include <stdio.h>
#include <stdlib.h>
int main()
{
int k, j, m, n, l, z, count1 = 0, count2 = 0, count3 = 0, count4 = 0, count5 = 0, count6 = 0;
char str[10000], chh, chhh;
char ch, file_name[75];
FILE *fp;
printf("Enter the name of file you wish to see with extension .c or .txt\n");
gets_s(file_name);
fp = fopen_s(file_name, "r"); // reads the file
if (fp == NULL)
{
perror("Error while opening the file.\n");
_getche();
exit(EXIT_FAILURE);
}
printf("The contents of %s file are :\n", file_name); //prints out the text
int i = 0;
while ((ch = fgetc(fp)) != EOF) {
printf("%c", ch);
str[i] = ch;
i++;
}
int fsize = i;
// code above opens up the symbols of the file, code below searches for specific symbols
int count = 0;
printf("\nEnter the character to be searched : "); //which symbol to search
scanf_s("%c", &chh);
for (i = 0; i < fsize; i++) {
if (str[i] == chh)
count++;
}
if (count == 0)
printf("\nCharacter '%c' is not present", chh); //if there isn't one
else
printf("\nOccurence of character '%c' : %d", chh, count); //prints their number if there is
for (k = 0; k<fsize; k++) {
if (str[k] == '>')
count1++;
}
for (j = 0; j<fsize; j++) {
if (str[j] == '<')
count2++;
}
for (m = 0; m<fsize - 1; m++) {
if (str[m] == '=' && str[m + 1] == '=')
count3++;
}
for (n = 0; n<fsize - 4; n++) {
if (str[n] == 'e' && str[n + 1] == 'l' && str[n + 2] == 's' && str[n + 3] == 'e')
count4++;
}
for (l = 0; l<fsize - 2; l++) {
if (str[l] == 'i' && str[l + 1] == 'f')
count5++;
}
int br;
br = count4 + count5;
printf("\nOccurence of character '%c' : %d", '>', count1);
printf("\nOccurence of character '%c' : %d", '<', count2);
printf("\nOccurence of character == : %d ", count3);
printf("\nOccurence of character else : %d ", count4);
printf("\nOccurence of character if: %d \n", count5);
printf("\nobsht broi if+else: %d ", br);
fclose(fp);
return 0;
}
It prints out the text inside a file, searches for a specific character you want and prints out its occurrence.
PS: when I try to run it on my PC, Visual Studio spits out a bunch of errors and warnings. I'm puzzled as to how to get rid of them.
Errors image
Thanks !
Using GCC I was able to compile this by changing a few methods.
changed gets_s to gets(file_name) which produces a warning that this is an unsafe function.
changed _getche() to getchar()
changed scanf_s() to scanf()
change fopen_s() to fopen()
This code compiled and ran using GCC on Linux
#include <stdio.h>
#include <stdlib.h>
int main()
{
int k, j, m, n, l, z, count1 = 0, count2 = 0, count3 = 0, count4 = 0, count5 = 0, count6 = 0;
char str[10000], chh, chhh;
char ch, file_name[75];
FILE *fp;
printf("Enter the name of file you wish to see with extension .c or .txt\n");
gets(file_name);
fp = fopen(file_name, "r"); // reads the file
if (fp == NULL)
{
perror("Error while opening the file.\n");
getchar();
exit(EXIT_FAILURE);
}
printf("The contents of %s file are :\n", file_name); //prints out the text
int i = 0;
while ((ch = fgetc(fp)) != EOF) {
printf("%c", ch);
str[i] = ch;
i++;
}
int fsize = i;
// code above opens up the symbols of the file, code below searches for specific symbols
int count = 0;
printf("\nEnter the character to be searched : "); //which symbol to search
scanf("%c", &chh);
for (i = 0; i < fsize; i++) {
if (str[i] == chh)
count++;
}
if (count == 0)
printf("\nCharacter '%c' is not present", chh); //if there isn't one
else
printf("\nOccurence of character '%c' : %d", chh, count); //prints their number if there is
for (k = 0; k<fsize; k++) {
if (str[k] == '>')
count1++;
}
for (j = 0; j<fsize; j++) {
if (str[j] == '<')
count2++;
}
for (m = 0; m<fsize - 1; m++) {
if (str[m] == '=' && str[m + 1] == '=')
count3++;
}
for (n = 0; n<fsize - 4; n++) {
if (str[n] == 'e' && str[n + 1] == 'l' && str[n + 2] == 's' && str[n + 3] == 'e')
count4++;
}
for (l = 0; l<fsize - 2; l++) {
if (str[l] == 'i' && str[l + 1] == 'f')
count5++;
}
int br;
br = count4 + count5;
printf("\nOccurence of character '%c' : %d", '>', count1);
printf("\nOccurence of character '%c' : %d", '<', count2);
printf("\nOccurence of character == : %d ", count3);
printf("\nOccurence of character else : %d ", count4);
printf("\nOccurence of character if: %d \n", count5);
printf("\nobsht broi if+else: %d \n", br);
fclose(fp);
return 0;
}
Please find my findings below.
gets_s(file_name); -> i dont think this is correct. gets_s Takes up 2 argument and not 1 please use gets instead and try it out or simple scanf to check if it is working.
2._getche() Please use #include header file for that function. Using it would avoid this issue.
fopen_s -> Fopen has invalid set of arguments. U need a file pointer as the first argument. Please re-frame the function used. Better go for fopen which has 2 arguments.
scanf_s -> has an argument(parameter) where you can specify the buffer size. Hence the above code sacnf_s function u have used is syntaticaly wrong. Please change it accordingly.
Please find the changed code which is commonly used. I have taken the liberty of changing the gets_s to gets, fopen_s to fopen and scanf_s to scanf and have build it. No errors. Please find the code below for your reference.
#include <stdio.h>
#include <stdlib.h>
#include<conio.h>
FILE *fp;
int main()
{
int k, j, m, n, l, z, count1 = 0, count2 = 0, count3 = 0, count4 = 0, count5 = 0, count6 = 0;
char str[10000], chh, chhh;
char ch, file_name[75];
printf("Enter the name of file you wish to see with extension .c or .txt\n");
gets(file_name);
fp = fopen(file_name, "r"); // reads the file
if (fp == NULL)
{
perror("Error while opening the file.\n");
getchar();
exit(EXIT_FAILURE);
}
printf("The contents of %s file are :\n", file_name); //prints out the text
int i = 0;
while ((ch = fgetc(fp)) != EOF) {
printf("%c", ch);
str[i] = ch;
i++;
}
int fsize = i;
// code above opens up the symbols of the file, code below searches for specific symbols
int count = 0;
printf("\nEnter the character to be searched : "); //which symbol to search
scanf_s("%c", &chh);
for (i = 0; i < fsize; i++) {
if (str[i] == chh)
count++;
}
if (count == 0)
printf("\nCharacter '%c' is not present", chh); //if there isn't one
else
printf("\nOccurence of character '%c' : %d", chh, count); //prints their number if there is
for (k = 0; k<fsize; k++) {
if (str[k] == '>')
count1++;
}
for (j = 0; j<fsize; j++) {
if (str[j] == '<')
count2++;
}
for (m = 0; m<fsize - 1; m++) {
if (str[m] == '=' && str[m + 1] == '=')
count3++;
}
for (n = 0; n<fsize - 4; n++) {
if (str[n] == 'e' && str[n + 1] == 'l' && str[n + 2] == 's' && str[n + 3] == 'e')
count4++;
}
for (l = 0; l<fsize - 2; l++) {
if (str[l] == 'i' && str[l + 1] == 'f')
count5++;
}
int br;
br = count4 + count5;
printf("\nOccurence of character '%c' : %d", '>', count1);
printf("\nOccurence of character '%c' : %d", '<', count2);
printf("\nOccurence of character == : %d ", count3);
printf("\nOccurence of character else : %d ", count4);
printf("\nOccurence of character if: %d \n", count5);
printf("\nobsht broi if+else: %d ", br);
fclose(fp);
return 0;
}
At any point of time if u need any assistance please ping me :) Thank you.

C: Occurrence of Letters in Text file

Program takes an input file through the command line and outputs the occurrence of each letter in the text file. Not sure where I went wrong.
int main(int argc, char *argv[]) {
char word[1000];
int a = 0;
int b = 0;
int d = 0;
int c = 0;
int e = 0;
int f = 0;
int g = 0;
int h = 0;
int i = 0;
int j = 0;
int k = 0;
int l = 0;
int m = 0;
int n = 0;
int o = 0;
int p = 0;
int q = 0;
int r = 0;
int s = 0;
int t = 0;
int u = 0;
int v = 0;
int w = 0;
int x = 0;
int y = 0;
int z = 0;
int other = 0;
int counter, lenght;
FILE *fp = fopen(argv[1], "r");
fgets(word, 999, fp);
lenght = 1000;
for(counter = 0; counter < lenght; counter++) {
word[counter] = tolower(word[counter]);
if (word[counter] == 'a') {
a++;
}
else if (word[counter] == 'b') {
b++;
}
else if (word[counter] == 'c') {
c++;
}
else if (word[counter] == 'd') {
d++;
}
else if (word[counter] == 'e') {
e++;
}
else if (word[counter] == 'f') {
f++;
}
else if (word[counter] == 'g') {
g++;
}
else if (word[counter] == 'h') {
h++;
}
else if (word[counter] == 'i') {
i++;
}
else if (word[counter] == 'j') {
j++;
}
else if (word[counter] == 'k') {
k++;
}
else if (word[counter] == 'l') {
l++;
}
else if (word[counter] == 'm') {
m++;
}
else if (word[counter] == 'n') {
n++;
}
else if (word[counter] == 'o') {
o++;
}
else if (word[counter] == 'p') {
p++;
}
else if (word[counter] == 'q') {
q++;
}
else if (word[counter] == 'r') {
r++;
}
else if (word[counter] == 's') {
s++;
}
else if (word[counter] == 't') {
t++;
}
else if (word[counter] == 'u') {
u++;
}
else if (word[counter] == 'v') {
v++;
}
else if (word[counter] == 'w') {
w++;
}
else if (word[counter] == 'x') {
x++;
}
else if (word[counter] == 'y') {
y++;
}
else if (word[counter] == 'z') {
z++;
}
else {
other++;
}
}
printf("\nCharacter frequency in %s", argv[1]);
printf("\nCharacter Count");
printf("\na \t\t %d", a);
printf("\nb \t\t %d", b);
printf("\nc \t\t %d", c);
printf("\nd \t\t %d", d);
printf("\ne \t\t %d", e);
printf("\nf \t\t %d", f);
printf("\ng \t\t %d", g);
printf("\nh \t\t %d", h);
printf("\ni \t\t %d", i);
printf("\nj \t\t %d", j);
printf("\nk \t\t %d", k);
printf("\nl \t\t %d", l);
printf("\nm \t\t %d", m);
printf("\nn \t\t %d", n);
printf("\no \t\t %d", o);
printf("\np \t\t %d", p);
printf("\nq \t\t %d", q);
printf("\nr \t\t %d", r);
printf("\ns \t\t %d", s);
printf("\nt \t\t %d", t);
printf("\nu \t\t %d", u);
printf("\nv \t\t %d", v);
printf("\nw \t\t %d", w);
printf("\nx \t\t %d", x);
printf("\ny \t\t %d", y);
printf("\nz \t\t %d", z);
fclose(fp);
return 0;
}
Should output in two columns one being the letter and the next being the number of times that letter occurs
There are problems in your code:
you do not include <stdio.h> nor <ctype.h>
you only read one line and you do not even check if that succeeds. You should write a loop like while (fgets(word, sizeof word, fp)) {
you check all characters in the word array: you should stop at the end of the line: lenght = strlen(word);
tolower() should not be given a char argument, because on platforms where char is signed, negative values invoke undefined behavior. You can cast the argument as (unsigned char) to avoid this: word[counter] = tolower((unsigned char)word[counter]);
More room for improvement:
lenght is misspelt, it should be length.
you should use an array of counters to avoid all these tests and all these explicit printf statements.
check the argument count and fopen() success
no need to read line by line, handle one byte at a time read with getc(). However, reading one large chunk at a time can be faster because it uses fewer tests and locks.
the printf statements should output the newline at the end rather than at the beginning.
Here is a corrected and simplified version:
#include <ctype.h>
#include <limits.h>
#include <stdio.h>
int main(int argc, char *argv[]) {
int count[UCHAR_MAX + 1] = { 0 };
int other, total;
int c;
const char *s;
FILE *fp;
if (argc <= 1) {
fprintf(stderr, "missing input file\n");
return 1;
}
fp = fopen(argv[1], "r");
if (fp == NULL) {
fprintf(stderr, "cannot open input file %s\n", argv[1]);
return 1;
}
total = 0;
while ((c = getc(fp)) != EOF) {
count[tolower(c)] += 1;
total++;
}
printf("Character frequency in %s\n", argv[1]);
printf("Character Count\n");
other = total;
for (s = "abcdefghijklmnopqrstuvwxyz"; *s; s++) {
printf("%c:\t%9d\n", *s, count[(unsigned char)*s]);
other -= count[(unsigned char)*s];
}
printf("other:\t%9d\n", other);
fclose(fp);
return 0;
}
Reading the file by chunks instead of one byte at a time improves the speed dramatically with recent C libraries, because the support for multithreading has made the getc() macros inefficient. Using 64K buffers, the code below is fifty times faster (50X) for a 400MB file:
#include <ctype.h>
#include <limits.h>
#include <stdio.h>
#define BUFFER_SIZE 65536
int main(int argc, char *argv[]) {
unsigned char buffer[BUFFER_SIZE];
long count[UCHAR_MAX + 1] = { 0 };
long other;
size_t i, n;
const char *s;
FILE *fp;
if (argc <= 1) {
fprintf(stderr, "missing input file\n");
return 1;
}
fp = fopen(argv[1], "r");
if (fp == NULL) {
fprintf(stderr, "cannot open input file %s\n", argv[1]);
return 1;
}
while ((n = fread(buffer, 1, sizeof buffer, fp)) != 0) {
for (i = 0; i < n; i++) {
count[buffer[i]] += 1;
}
}
other = 0;
for (i = 0; i <= UCHAR_MAX; i++) {
if (isupper(i)) {
count[tolower(i)] += count[i];
} else {
if (!islower(i))
other += count[i];
}
}
printf("Character frequency in %s\n", argv[1]);
printf("Character Count\n");
for (s = "abcdefghijklmnopqrstuvwxyz"; *s; s++) {
printf("%c:\t%9ld\n", *s, count[(unsigned char)*s]);
}
printf("other:\t%9ld\n", other);
fclose(fp);
return 0;
}
Here's a quick implementation I wrote. It doesn't use fgets, but that is most definitely an option.
The flow of the program should be simple, but it is as follows:
Check for a proper argument count.
Declare the variables we'll need.
Declare the file pointer and attempt to open the file.
If the file doesn't open, we'll error out.
Read in every character from the file one at a time and store it into our variable c.
Using our ascii table, we'll alter the values to get them into the proper position in our array.
Print out all of our values.
Close the file.
#include <stdio.h>
int main(int argc, char **argv){
if (argc < 2){
printf("Not enough arguments!\n");
return -1;
}
int A[27] = {0}, c;
FILE *inFile = fopen(argv[1], "r");
if (inFile == NULL){
printf("The file \"%s\" could not be opened.\n", argv[1]);
return -2;
}
while((c = fgetc(inFile)) != EOF){
if ( c >= 'a' && c <= 'z' ){
/* C is a lowercase character */
c-='a';
A[c]++;
}
else if ( c >= 'A' && c <= 'Z' ){
/* C is an uppercase character */
c-='A';
A[c]++;
}
else if (c == '\n'){
/* we're not counting newlines */
continue;
}
else {
A[26]++;
}
}
/* Print out all the values except the "Other" count. */
for (c = 0; c < sizeof A / sizeof A[0] - 1; c++){
printf("%c: %d\n", c+'a', A[c]);
} printf("Other: %d\n", A[26]); //Print out "Other" count
/* Close our file */
fclose(inFile);
return 0;
}

I can't read the second string, no matter how many getchar i insert

This program need to read two strings, this two strings will be passed to the "confirm" function, they will be read and the the function will have to find a word in common.
But in the main i cant read the "string2" string! No matter how many getchar i insert.
#include <stdio.h>
#include <string.h>
void confirm(char string1[],char string2[]){
char word[20];
char w_aux[20];
int i, j, k, l, m;
int len1, len2;
int find;
i = 0;
len1 = strlen(string1);
len2 = strlen(string2);
while (i < len1){
j = 0;
while ((string1[i] != ' ') && (i < len1)){
word[j] = string1[i];
i++;
j++;
}
word[j] = '\0';
k = 0;
find = 0;
while((k < len2) && (find == 0)){
l = 0;
while ((string2[k] != ' ') && (k < len2)){
w_aux[l] = string2[k];
k++;
l++;
}
w_aux[l] = '\0';
if (j == l){
m = 0;
while((word[m] == w_aux[m]) && (m<j)){
m++;
}
if (m == j){
find = 1;
}
}
k++;
}
i++;
}
printf("%s\n", word);
}
int main (){
char string1[20];
char string2[20];
printf("Type the first text: \n");
scanf("%[^\n]s", string1);
printf("Type the second text: \n");
scanf("%[^\n]s", string2);
getchar();
confirm(string1, string2);
return 0;
}
Use getchar after input of string 1 for \n:
printf("Type the first text: \n");
scanf("%[^\n]", string1);
getchar(); //here
printf("Type the second text: \n");
scanf("%[^\n]", string2);
Just change the format specifier to "%19[^\n]*c", it will take the trailing '\n' character away.

Resources