Segmentation fault (Core Dumped)-- Structures and Pointers--C language - c

I have gotten my code to compile, but after running and entering input, the core dumps. I am aware this this must be from a pointer problem, but I am unaware of where the problem stems. The goal of the code is to take user input of a DNA sequence, then print out how many times each base was entered. Thank you in advance for your responses!
#include <stdio.h>
#include <string.h>
#define N 25
void countBase (char *dnaSequence, int n) //countBase function declaration
{
int i;
char *p;
struct
{
int aCount;
int cCount;
int tCount;
int gCount;
}dnaCount;
p = &dnaSequence[0];
for (p = 0; i < N; p++)
{
if (*p == 'A' || *p =='a')
{
dnaCount.aCount++;
}
if (*p == 'C' || *p == 'c')
{
dnaCount.cCount++;
}
if (*p == 'T' || *p == 't')
{
dnaCount.tCount++;
}
if (*p == 'G' || *p == 'g')
{
dnaCount.gCount++;
}
}
printf("Number of A's : %d\n", dnaCount.aCount);
printf("Number of C's : %d\n", dnaCount.cCount);
printf("Number of T's : %d\n", dnaCount.tCount);
printf("Number of G's : %d\n", dnaCount.gCount);
}
int main(int argc, char *argv[])
{
char dnaSequence [N];
printf("Enter a DNA sequence\n"); //prints prompt
fgets(dnaSequence, N, stdin); //retrieves user input
printf("Sequence: \n%s", dnaSequence); //prints entered sequence
countBase(dnaSequence, N); //function call
return 0; //terminating line
}

You have several issues going on there:
A runaway pointer - you do not increment i in the for loop (it turns out that you do not need i at all - read on)
You ignore n passed into the function, using N instead - you do not need to pass n either, but if you choose to do it, you should use it in the loop
Your counters are not initialized - you need to set counters to zero, or zero out the entire struct.
Here is how you can fix your code:
void countBase (char *p) {
struct {
int aCount;
int cCount;
int tCount;
int gCount;
} dnaCount = {0}; // Set all counters to zero
// Loop will end when you reach the end of null-terminated string
while (*p) {
if (*p == 'A' || *p =='a') {
dnaCount.aCount++;
} else if (*p == 'C' || *p == 'c') {
dnaCount.cCount++;
} else if (*p == 'T' || *p == 't') {
dnaCount.tCount++;
} else if (*p == 'G' || *p == 'g') {
dnaCount.gCount++;
}
p++;
}
printf("Number of A's : %d\n", dnaCount.aCount);
printf("Number of C's : %d\n", dnaCount.cCount);
printf("Number of T's : %d\n", dnaCount.tCount);
printf("Number of G's : %d\n", dnaCount.gCount);
}

You never initialized i , nor dnaCount. Change int i; to:
int i = 0;
and also zero-initialize your counters. Using uninitialized variables causes undefined behaviour.

Related

Pure Pointer notation in C

I have this coding assignment where I have to use pure pointer notation only. I am pretty much finished with it but I just realized that I used an array. I am not allowed to do so, unless I change it into a pointer somehow. That's where I am slightly stuck.
This is my code.
#include <stdio.h>
#include <stdlib.h>
/* Function Prototypes */
int main();
void s1(char *random);
void s2(char *s2_input, int index);
void strfilter(char *random, char *s2_input, char replacement);
int main()
{
for(;;)
{
int s1_index = 41;
char s1_random[s1_index];
s1(s1_random);
printf("\ns1 = ");
puts(s1_random);
printf("s2 = ");
int s2_index = 21;
char s2_input[s2_index];
s2(s2_input, s2_index);
if(s2_input[1] == '\0')
{
printf("Size too small");
exit(0);
}
if(s2_input[21] != '\0' )
{
printf("Size too big");
exit(0);
}
printf("ch = ");
int replacement = getchar();
if(replacement == EOF)
break;
while(getchar() != '\n');
printf("\n");
strfilter(s1_random, s2_input, replacement);
printf("\ns1 filtered = ");
puts(s1_random);
printf("Do you wish to run again? Yes(Y), No(N) ");
int run = getchar();
// or include ctype.h and do:
// run == EOF || toupper(run) == 'N'
if(run == EOF || run == 'N' || run == 'n')
break;
while(getchar() != '\n');
}
}
void s1(char *random)
{
int limit = 0;
char characters;
while((characters = (('A' + (rand() % 26))))) /* random generator */
{
if(limit == 41)
{
*(random + 41 - 1) = '\0';
break;
}
*(random + limit) = characters;
limit++;
}
}
void s2(char *s2_input, int index)
{
char array[21] = "123456789012345678901"; /* populated array to make sure no random memory is made */
char input;
int count = 0;
int check = 0;
while((input = getchar() ))
{
if(input == '\n')
{
*(s2_input + count) = '\0';
break;
}
else if(input < 65 || input > 90)
{
printf("invalid input");
exit(0);
}
*(s2_input + count) = input;
count++;
}
index = count;
}
void strfilter(char *random, char *s2_input, char replacement) /* replacement function */
{
while(*s2_input)
{
char *temp = random;
while(*temp)
{
if(*temp == *s2_input)
*temp = replacement;
temp++;
}
s2_input++;
}
}
My issue is this part I am not sure how to edit this to not include an array, and still have it output the program in the same way.
if(s2_input[1] == '\0')
{
printf("Size too small");
exit(0);
}
if(s2_input[21] != '\0' )
{
printf("Size too big");
exit(0);
}
I tried to take the address of the array at a certain point, and then dereference it with a pointer, however that is still using a array. Which is what I am trying to avoid. Any help would be greatly appreciated!
s2_input[i] can be written as *(s2_input+i) where i is some index.
if ((s2_input[1]) == '\0')
is equivalent to:
if (*(s2 + 1) == '\0')
Which means to dereference the value at s2 (which is the location of the zeroth[0] element), and add one to it.
The same could be done for any other location.
Pointer notation and what is often referred to as Indexed notation (which uses the [ ] subscript operator) are entirely equivalent. Either notion provides the pointer address plus an offset from that pointer address. See C11 Standard - 6.5.2.1 Array subscripting That being array[offset] or *(array + offset)1
For example accessing the first element using *array is shorthand for *(array + 0) which is simply array[0] in indexed notation. The 0 being the offset (in elements of that type) from the original pointer address. (type controls pointer arithmetic)
So array[10] is simply *(array + 10). If array is type char, array[10] is 10-bytes after array address. If array is type int (where an int is 4-bytes), then array[10] is 40-bytes after array address (10-int).
For a 2D array, the notation for arr2d[1][2] would simply be *(arr2d[1] + 2) which expanded further is simply *(*(arr2d + 1) + 2).
So generally array[i] is *(array + i) and arr2d[i][j] is *(*(arr2d + i) + j).
footnotes:
It follows that array[offset] is equivalent to *(array + offset) is equivalent to offset[array].

How do I remove duplicate vowels from a string?

Question: Define an int function that removes all consecutive vowel repetitions from a string. The function should return the number of vowels removed and present the string without duplicates.
I am PT so Vogais is Vowels; Digite uma String is Write one String. A String sem duplicados fica assim ' %s ' e foram retiradas %d vogais is The string without duplicates is ' %s ' and where removed %d vowels.
Explanation: In portuguese we have some words with two consecutive vowels like: coordenador, coordenação (chqrlie example). But in thouse cases should be ignored in the context of this problem.
Problem: When I test a string like 'ooooo' it says the string without duplicate vogals is 'oo' and where removed 3 vowels. But it should be 'o' and 4 vowels removed. Another example with error is 'Estaa e umaa string coom duuuplicadoos', I am getting ' Esta e uma string com duplcdos ' and 8 vowels removed.
Note: This is a simple question so there isn't need to complicate. It only askes the consecutive duplicate vowels. The cases 'oOoO' -> 'oO' ,'abAb'->'abAb','abab' -> 'ab','aba'-> 'aba',... are in another chapter XD.
int Vogais(char *s) {
if (*s == 'A' || *s == 'a' || *s == 'E' || *s == 'e'
|| *s == 'I' || *s == 'i' || *s == 'O' || *s == 'o'
|| *s == 'U' || *s == 'u') return 1;
return 0;
}
int retiraVogaisRep(char *s) {
int res = 0;
for (int i = 0; i < strlen(s); i++) {
for (int j = i + 1; s[j] != '\0'; j++) {
if (s[i] == s[j] && Vogais(&s[j]) == 1) {
res++;
for (int k = j; s[k] != '\0'; k++) {
s[k] = s[k + 1];
}
}
}
}
return res;
}
int main() {
char s[38];
printf("Digite uma String:\n");
scanf("%[^\n]", s);
int res = retiraVogaisRep(s);
printf("A String sem duplicados fica assim ' %s ' e foram retiradas %d vogais.\n", s, res);
return 0;
}
Your code is too complicated: there is no need for nested loops for this task and you do not set the null terminator when shortening the string.
Here is a simpler version:
#include <stdio.h>
#include <string.h>
int retiraVogaisRep(char *s) {
int i, j; // use 2 running indices
char c, last = 0;
for (i = j = 0; (c = s[i]) != '\0'; i++) {
if (c != last || !strchr("aeiouAEIOU", c))
s[j++] = last = c;
}
s[j] = '\0'; // set the null terminator
return i - j; // return the number of bytes removed
}
int main() {
char s[100];
printf("Digite uma String:\n");
// read the user input safely with `fgets()`
if (!fgets(s, sizeof s, stdin))
return 1;
// strip the trailing newline if any
s[strcspn(s, "\n")] = '\0';
// remove duplicate consecutive vowels
int res = retiraVogaisRep(s);
printf("A String sem duplicados fica assim ' %s ' e foram retiradas %d vogais.\n", s, res);
return 0;
}
The question tag is C, but I will not post the actual code here.
The pseudocode:
function is_vowel(int c) {...}
start loop c = <src>
if next_char is past the last char then quit loop;
if is_vowel(c) and c == next_char and is_vowel(next_char)
then continue;
else
copy c to <dst>
You should elaborate on this, as the above is possibly having small issues. Nevertheless, I think this answer is somewhat shorter and gives an insight.
Update
The above is definitly have an issue, in that the next char does not copied to the output. The mistake is easy to correct, so I will leave it up to OP.
Update
Edited above code to indicate that OP wants to remove only identical duplicates. So, the case of a charcter is important.
Rather than a triple nested loop, consider a single walk down the string, looking for repeats.
#include <stdio.h>
#include <ctype.h>
int Vogais(unsigned char s) {
if (s == 'A' || s == 'a' || s == 'E' || s == 'e'
|| s == 'I' || s == 'i' || s == 'O' || s == 'o'
|| s == 'U' || s == 'u') return 1;
return 0;
}
int retiraVogaisRep(char *s) {
unsigned char *us = (unsigned char *) s;
unsigned char *dest = us;
int res = 0;
int prior = EOF;
while (*us) {
while (toupper(*us) == prior) {
us++;
res++;
}
prior = Vogais(*us) ? toupper(*us) : EOF;
*dest++ = *us++;
}
*dest = '\0';
return res;
}
int main() {
char buf[100] = "OoFreedaa";
printf("%d\t", retiraVogaisRep(buf));
printf("<%s>\n", buf);
return 0;
}
Output
3 <OFreda>
Remove consecutive duplicate vowels
You should use tolower function from ctype.h to check for vowels, that include the letter 'y', see below working code:
You can store previous character in prev and compare it to the current character, as you are case insensitive you store the tolower version.
#include <string.h>
#include <stdio.h>
#include <ctype.h>
int Vogais(char c){
return (c == 'a' || c == 'e' || c == 'i' || c == 'o' || c == 'u' || c == 'y') ;
}
int retiraVogaisRep (unsigned char *s){
if (*s == NULL)
return 0;
unsigned char t[256];
memset(t, 0, sizeof(t));
int res = 0;
int j = 0;
t[0] = s[0];
char prev = tolower(s[0]);
int len = strlen(s);
for (int i = 1; i < len; i++) {
char c = tolower(s[i]);
if (Vogais(c) && c == prev)
++res;
else
t[j++] = s[i];
prev = c;
}
memcpy(s, t, sizeof(t));
return res;
}
int main(){
char s[256];
printf("Digite uma String:\n");
scanf("%255[^\n]", s);
int res = retiraVogaisRep(s);
printf("Da String ' %s ' podem ser retiradas %d vogais.\n", s,res);
return 0;
}
Retaining the uppercase, using the Kernighan-copy
#include <stdio.h>
#include <string.h>
#include <ctype.h>
size_t remove_duplicate_vowels(char *str)
{
int old,new;
size_t dst,src;
old = 0;
for(dst=src=0; str[dst] = str[src]; old=new, src++ ) {
new = toupper( str[dst] );
if ( !strchr( "AEIOU", new )) { // Not a vowel
dst++; continue;
}
if ( new != old ) { // Not a repetition
dst++; continue;
}
}
return src - dst;
}
int main(int argc, char **argv)
{
char test[] = "Aaa bbBb CccCC d eEeee!";
char *arg;
size_t ret;
arg = argv[1] ? argv[1] : test;
ret = remove_duplicate_vowels(arg);
fprintf(stderr, "[%zu]: %s\n", ret, arg);
return 0;
}

Writing my own atoi function

I am trying to convert a string of numerical characters to their corresponding integral form. Please suggest what is wrong with the code. I would like to stick with pointers. I understand that the pointer str points to the first character in my string. So, each time I call my function in the loop, I want the pointer to increment by 1, and add the value of the character to one node in my array. For some reason, though I am unable to do so. Here is the code.
#include <stdio.h>
#include <string.h>
#include <malloc.h>
#include <stdlib.h>
int ctoi(char *c);
int main (void)
{
char *str;
int A[20];
int i = 0;
str = (char*) malloc(20 * sizeof(char));
printf("Input the string. ");
scanf("%s", str);
while(str != '\0')
{
A[i] = ctoi(str);
i++;
str++;
}
for(i = 0; i < strlen(str); i++)
printf("%d", A[i]);
getchar();
getchar();
return 0;
}
int ctoi(char *c)
{
int a;
a= *c - '0';
return a;
}
for (i=0;i<strlen(str);i++)
printf("%d", A[i]);
Here strlen will return 0 because you updated str in your previous loop .Replace it with :
for(i=0;i<len;i++)
where len is the length of your input string .Find it before using str in while loop
while(str!='\0') should be `while(*str!='\0')`
. You will get it . But for writing your own atoi function you dont need to store the number in an array
Please try this it works, the myatoi() function was lifted perhaps 20 years ago from the classic "THE C PROGRAMMING LANGUAGE" , get the book.
#include <stdio.h>
main()
{
char temp[99];
strcpy(temp , "34");
printf( "\n %d " , myatoi(temp));
strcpy( temp , "8642");
printf( "\n %d " , myatoi(temp));
}
int myatoi( char s[])
{
int i,n,sign;
// skip white space
for( i=0 ; s[i]==' ' || s[i]=='\n' ||s[i]=='\t';i++) ;
sign=1;
if( s[i]=='+' || s[i]=='-')
sign=( s[i++]=='+' ? 1 : -1 );
for( n=0; s[i]>='0' && s[i]<='9' ; i++)
n=10*n+s[i]-'0' ;
return(sign*n);
}
OP's code needs a few (at least 2) fixes to mostly work. See ***
int main (void)
{
char *str;
int A[20];
int i = 0;
// *** Cast not needed, '* sizeof(char)' not needed
str = malloc(20);
printf("Input the string. ");
scanf("%s", str);
// ***
char *str_original = str;
while(*str != '\0')
{
A[i] = ctoi(str);
i++;
str++;
}
// ***
str = str_original;
for(i = 0; i < strlen(str); i++)
printf("%d", A[i]);
// ***
free(str); // Good to return memory
str = NULL;
getchar();
getchar();
return 0;
}
A simple way to convert a string to an int
int strtoi(const char *s) {
int sum = 0;
char ch;
char sign = *s;
if (*s == '-' || *s == '+') s++;
while ((ch = *s++) >= '0' && ch <= '9') {
sum = sum * 10 - (ch - '0');
}
if (sign != '-') {
sum = -sum;
}
return sum;
}
Notes: This code accumulates the sum on the negative side of 0 to avoid UB when trying to parse the string for INT_MIN. Modified code could skip leading white-space, add text error detection, overflow detection, etc.
Here is my custom atoi funtion, who handle unsigned int with debug gestion:
int my_getnbr(char *str)
{
int nb;
int sign;
int i;
nb = 0;
sign = 0;
i = -1;
if (!str)
return (0);
while (str[++i])
if (str[i] < '0' && str[i] > '9' && str[i] != '-' && str[i] != '+')
return (0);
i = 0;
while (str[i] != '\0' && (str[i] == '-' || str[i] == '+'))
if (str[i++] == '-')
++sign;
while (str[i] && (str[i] >= '0' && str[i] <= '9'))
{
nb = (nb * 10) + (str[i++] - '0');
if (str[i] == ' ')
i++;
}
return (((sign % 2) == 1) ? ((nb) * (-1)) : (nb));
}
tested with that main:
int main()
{
printf("%d\n", my_getnbr("-42"));
printf("%d\n", my_getnbr("-+-+--42"));
printf("%d\n", my_getnbr("-0"));
printf("%d\n", my_getnbr("590310"));
return (0);
}
No leaks, here is the result:
-42
42
0
590310
Firstly
while(str!='\0') should be
while(*str!='\0')
You should compare the content, not the address.
And while printing the returned data, you are doing
for(i=0;i<strlen(str);i++)
printf("%d", A[i]);
str already parsed till the last. So length would probably be 0.
Change your while loop to
while(*str!='\0')
{
A[i]=ctoi(*str);
i++;
str++;
}
And your function to
int ctoi(char c)
{
int a;
a= c-'0';
return a;
}
There are several approaches for a simple atoi replacement without the base conversion flexibility in strtol. The simplest is generally to find the length of the string to convert, and then work backward toward the front of the string preforming the conversion from string to integer as you go. A quick example would be:
/* a quick atoi replacement */
int atoi2 (char *s)
{
int nmax = (1ULL << 31) - 1; /* INT_MAX */
long long n = 0; /* the number to return */
size_t m = 1; /* multiplier for place */
size_t l = 0; /* length of string */
char *p = s;
while (*p++) l++; /* get string length */
p -= 2; /* position at last char */
while (l--) /* for each char in string */
{ /* verify a digit or '-' sign */
if ((*p >= '0' && *p <= '9') || *p == '-')
{
if (*p == '-') { /* if '-' is first char */
if (p == s) n = -n; /* negate value */
}
else { /* otherwise normal conversion */
n += (*p - '0') * m;
if (n > nmax) { /* prevent overflow */
fprintf (stderr, "atoi2() error: conversion > INT_MAX.\n");
exit (EXIT_FAILURE);
}
m *= 10;
}
}
p--;
}
return (int) n;
}
A simple driver program to test could be:
#include <stdio.h>
#include <stdlib.h>
int atoi2 (char *s);
int main (int argc, char **argv) {
if (argc < 1) return 1;
printf ("\n string : %s, conversion : %d\n\n",
argv[1], atoi2 (argv[1]));
return 0;
}
Example Use/Output
$ ./bin/atoi2 321
string : 321, conversion : 321
$ ./bin/atoi2 -321
string : -321, conversion : -321
$ ./bin/atoi2 2147483647
string : 2147483647, conversion : 2147483647
$ ./bin/atoi2 2147483648
atoi2() error: conversion > INT_MAX.
If you have any questions, please do not hesitate to ask.
Here is a custom atoi function that avoids using most of the standard library functions
/*** _atoi - finds the first set of integers in a given string
* #s: string entered
* Return: first number sequence
**/
int _atoi(char *s)
{
int length = 0, negativeCount = 0, count = 0, num = 0;
while (s[length] != '\0')
{
length++;
}
while (count < length)
{
if (s[count] == '-')
{
negativeCount++;
}
if (s[count] >= 48 && s[count] <= 57)
{
/* ascii values for numbers */
for (; s[count] >= 48 && s[count] <= 57; count++)
{
num = (10 * num - (s[count] - 48));
}
break;
}
count++;
}
if (negativeCount % 2 != 0)
{
return (num);
}
else
{
return (-num);
}
}

convert a character value to integer value

here when ever i find 'h' i have to access the values between p and h i.e 123 and i want that has int and store it in value as 123 itself how can i do this can any one tell me the logic, that code that i have written is not working and how to copy the values when the pointer is getting incremented
main()
{
char *ptr1 = "p123h12";
int value;
while(*ptr1!= '\0')
{
if(*ptr1 == 'h')
{
value = (int)atoi(ptr1);
printf("%d\n", value);
}
ptr1++;
}
}
With sscanf:
int value;
sscanf (ptr1,"p%dh12",&value);
Update
int i,j;
int values[MAX_VALUES];
int startIdx = -1;
char *ptr1 = "p123hxxxxp124hxxxxp123145hxxxx";
char buffer[16];
for(i=0,j=0; i<strlen(ptr1);i++)
{
if(startIdx>=0 && ptr[i] == 'h')
{
strncpy(buffer,ptr1+startIdx,i-startIdx+1);
buffer[i-startIdx+1]='\0';
sscanf (buffer,"p%dh",&(values[j++]));
startIdx = -1;
}
else if(ptr[i] == 'p')
{
startIdx = i;
}
}
Here's a good possible starting point:
#include <stdio.h>
#include <ctype.h>
int main (void) {
char *p, *str = "p123h12p97h62p32h";
int accum = 0;
// Process every character.
for (p = str; *p != '\0'; p++) {
// 'p' resets the accumulator.
// 'h' outputs the accumulator.
// Any digit adjusts the accumulator.
if (*p == 'p') accum = 0;
if (*p == 'h') printf ("Processing %d\n", accum);
if (isdigit (*p)) accum = accum * 10 + *p - '0';
}
return 0;
}
This will work fine if your input string follows your specified format, outputting:
Processing 123
Processing 97
Processing 32
If there's the possibility that your input string is not so well formed, you'll need to add some defensive coding.

Problem finding the ratio of frequency of a word to total no of words in a text file in c

#include<conio.h>
#include<stdio.h>
#include<iostream.h>
#define NULL 0
int main()
{
char name[20],c;
int nw=0;
int j=0;
int t=0;
char s[] = "newas"; // find the frequency of this word in abc.txt
char p[5];
FILE *fpt;
//printf("Enter the name of file to be checked:- ");
//gets(name);
fpt=fopen("abc.txt","r");
if (fpt==NULL)
{
printf("ERROR - can/'t open file %s",name);
getch();
exit(0);
}
else
{
while ((c=getc(fpt))!=EOF)
{
switch(1)
{
case 1:
if (c==' ')
{
point:
while((c=getc(fpt))==' ');
if (c!=' ')
nw=nw+1;
// if(c==' ')
// nw--;
if(j < 5)
p[j++] = c;
printf("\n %c ",p[j]);
if(j == 5)
{
if(p == s)
{
t++;
j = 0;
}
}
}
if(c==' ')
{
j = 0;
goto point;
}
}
}
}
printf("\n The no. of words is %d. ",nw);
printf("\n Freq of words %s is %d. ",s,t);
getch();
}
The code above code is giving right answer for the total number of words but is not giving the right value of frequency of a particular word [s in given code], please comment on this, how to calculate frequency of a particular word in a text file.
As you are including iostream.h, I would guess this is supposed to be some form of C++, not C. If so, this is how you do word frequencies:
#include <iostream>
#include <map>
#include <string>
#include <fstream>
using namespace std;
typedef map <string, int> FreqMap;
int main() {
FreqMap frequencies;
ifstream ifs( "words.txt" );
string word;
while( ifs >> word ) {
frequencies[ word ] += 1;
}
for ( FreqMap::const_iterator it = frequencies.begin();
it != frequencies.end(); ++it ) {
cout << it->first << " " << it->second << "\n";
}
}
This code that looks for the interesting word:
if(p == s)
{
t++;
j = 0;
}
Is wrong. You can't compare strings like that in C, this only compares the pointer values, not the characters being pointed at (the string's content).
Assuming the rest of the code is set up properly, so that p really points at a true string, you can do this:
if(strcmp(p, s) == 0)
{
t++;
j = 0;
}
That requires that p points at a fully 0-terminated string, if it points at some character in the middle of a line the above won't work.
I'm not exactly answering the question, but this is some feedback that might help you on your way...
#include<conio.h>
#include<stdio.h>
#include<iostream.h>
#define NULL 0
int main()
{
/*
* GIVE YOUR VARIABLES NAMES THAT MAKE SENSE
* j, t, c, s, nw are meaningless to anybody picking up the code
*/
char name[20],c;
int nw=0;
int j=0;
int t=0;
char s[] = "newas"; // find the frequency of this word in abc.txt
/*
* Personally, I'd tend to have p as an array of 6, so that it's the same size as
* s and I'd initialize it to "", so that it's got a null terminator.
*/
char p[5];
FILE *fpt;
fpt=fopen("abc.txt","r");
if (fpt==NULL)
{
printf("ERROR - can/'t open file %s",name);
getch();
exit(0);
}
/*
* you don't need an else here... the other flow has already terminated */
*/
else
{
while ((c=getc(fpt))!=EOF)
{
/*
* What is the point of this switch statement? It may as well say if(true)
*/
switch(1)
{
case 1:
if (c==' ')
{
/*
* If you start using goto's in your code, it's usually a good sign that there's
* something wrong
*/
point:
/*
* It's hard to follow what you're doing because your variables don't have names
* and your code has no clear intent. If the while loop was in a function
* 'SkipToNextWord', the intent would be clearer, which would make it easier to find
* issues. What happens if there is a space at the end of your file?
*/
while((c=getc(fpt))==' ');
/*
* 'c' is never going to equal ' ', if it did, you'd still be in the while loop
*/
if (c!=' ')
nw=nw+1;
// if(c==' ')
// nw--;
if(j < 5)
p[j++] = c;
printf("\n %c ",p[j]);
/*
* This as written, could be a compound if statement...
* if(j == 5 && p == s)
*/
if(j == 5)
{
/*
* However, it looks like you're trying to do a string comparison?
* if(strncmp(p, s, sizeof(s)-1)==0)
*/
if(p == s)
{
t++;
/*
* This 'j=0' should be outside of the inner if, otherwise if there isn't a match
* you don't reset j to 0
*/
j = 0;
}
}
}
/*
* If you have a six letter word in your file, j is never reset to
* 0 and next time round the loop, you're not going to collect the
* letters correctly
*/
if(c==' ')
{
j = 0;
goto point;
}
}
}
}
printf("\n The no. of words is %d. ",nw);
printf("\n Freq of words %s is %d. ",s,t);
getch();
}
I think the following code will answer your question:
#include <stdio.h>
#include <conio.h>
int main(int argc, char* argv[])
{
char* name = "abc.txt";
char* word = "newas";
FILE* fpt = fopen(name, "rt");
int c;
int nw = 0;
int t = 0;
int i;
if (fpt == NULL)
{
printf("ERROR - can't open file %s\n", name);
getch();
return 0;
}
while ((c = getc(fpt)) != EOF)
{
// Skip spaces
if (c == ' ')
continue;
// Increase num of words
nw++;
// Check match
i = 0;
while ((c != EOF) && (c != ' ') && ((char)c == word[i]) && (word[i] != '\0'))
{
c = getc(fpt);
i++;
}
if (((c == ' ') || (c == EOF)) && (word[i] == '\0'))
t++;
// skip this word
while ((c != EOF) && (c != ' '))
c = getc(fpt);
}
fclose(fpt);
printf("\n The no. of words is %d.\n", nw);
printf("\n Freq of words %s is %d.\n", word, t);
getch();
return 0;
}

Resources