1

I'm writing a program that works with a string, converts it into an array of words, and stuff. Initially, I wrote it like

main()
{   char a[100];
    char *s;
    int len;
    getchar();
    printf("\nEnter string: ");
    gets(a);
    for(len=0;*(a+len)!='\0';len++);
    printf("\nLength is %d\n",len);
    s=malloc(sizeof(char)*len);
    s=a;
    //Rest of the program
}

and I used the string s for the rest of the program. It worked fine. The rest of the program separates words and prints them, and I could see the output.

Then I thought a was redundant and wrote

main()
{   char *s;
    int app_len;
    printf("\nEnter length of string(Approximate more than necessary): ");
    scanf("%d",&app_len);
    getchar();
    printf("\nEnter string: ");
    s=malloc(sizeof(char)*app_len);
    fgets(s,app_len+1,stdin);
    //Rest of the program
}   

When I ran the second version, and gave a valid input, there was no output, the command-prompt returned to the windows-equivalent of the dollar prompt.

Is something wrong with the way I used malloc; or fgets? After allocating memory space using malloc, am I only allowed to assign a value to it, and not to take input?

EDIT: Here's all my code. It works now :)

#include<stdio.h>
#include<stdlib.h>
void copy(char *dest,char *s)
{   int i;
    for(i=0;*(s+i)!='\0';i++)
        *(dest+i)=*(s+i);
    *(dest+i)='\0';
}   
int comp(char *s1,char *s2)
{   int i;
    for(i=0;!(*(s1+i)=='\0'||*(s2+i)=='\0');i++)
        if(*(s1+i)!=*(s2+i))
            return -1;
    return 0;
}   
int length(char *s)
{   int i;
    for(i=0;*(s+i)!='\0';i++);
    return i;
}   
main()
{   char b[20][20],words[20][20],unique[20][20],non[20][20];
    int i,j,k,len,no_of_words, c,count[100],w=0,u=0,nu=0;
    int mem = 64;
    char *s = malloc(mem);
    printf("\nEnter string : ");
    fgets(s, mem, stdin);
    while(s[length(s) - 1] != '\n')  //checks if we ran out of space
    {   mem *= 2;
        s = realloc(s, mem); //double the amount of space
        fgets(s + mem / 2 - 1, mem / 2 + 1, stdin);//read the rest (hopefully) of the line into the new space.
    }
    len=length(s);
    *(s+len--)='\0';
    printf("%s",s);
    for(i=0,j=0,k=0;i<len&&*(s+i)!='\0'&&*(s+i)!='\n';i++)
    {   if(*(s+i)==' ')
        {   *(*(b+j)+k)='\0';
            j++;
            k=0;
        }
        else
        {   
            *(*(b+j)+k)=*(s+i);//jth word, position k
            k++;
        }
    }
    *(*(b+j)+k)='\0';
    free(s);
    no_of_words=j+1;
    for(i=0;i<no_of_words;i++)
    {   for(j=0,c=0;j<w;j++)
        {   if(comp(*(b+i),*(words+j))==0)
                c++;
        }
        if(c==0)
        {   copy(*(words+w),*(b+i));
            w++;
        }
    }   
    for(j=0;j<w;j++)
    {   for(i=0,c=0;i<no_of_words;i++)
        {   if(comp(*(b+i),*(words+j))==0)
                c++;
        }
        if(c!=0)
        {   copy(*(non+nu),*(words+j));
            count[nu]=c;
            nu++;
        }
        if(c==1)
        {   copy(*(unique+u),*(words+j));
            u++;
        }
    }
    for(i=0,c=0;i<nu;i++)
        if(count[i]!=1)
            c++;
    printf("\nTotal no. of words = %d\n",no_of_words);
    printf("No. of distinct words = %d\n",w);
    printf("No. of distinct unique words = %d\n",u);
    printf("No. of distinct non-unique words = %d\n",c);
    printf("\nUnique words:\n");
    for(i=0;i<u;i++)
    {   printf("%s\n",*(unique+i));
    }
    printf("\nNon-unique words:\n");
    for(i=0;i<nu;i++)
        if(count[i]!=1)
            printf("%s\tFrequency=%d\n",*(non+i),count[i]);
    printf("\nList of all words and their frequencies:\n");         
    for(i=0;i<nu;i++)
            printf("%s\tFrequency=%d\n",*(non+i),count[i]); 
}   
9
  • You can omit the sizeof(char) in malloc. It's defined as 1. Commented Feb 4, 2014 at 18:11
  • 1
    you have memory leak s=a; use strcpy() instead, avoid using gets() use fget() Commented Feb 4, 2014 at 18:11
  • You are potentially overflowing your buffer. If the buffer length is app_len, then you may only input app_len-1 characters into the string and the argument to fgets should also be app_len. Commented Feb 4, 2014 at 18:15
  • s = strpy(malloc(len+1), a); Commented Feb 4, 2014 at 18:22
  • 1
    @Xephon I thought it was the C standard that forces sizeof(char) to be exactly 1. Could be wrong though. Commented Feb 4, 2014 at 20:54

1 Answer 1

1

In the first variant you are losing the just created field of s. And it works only until length(s)<100.

The second variant is OK for me. Maybe only put app_len+1 to both malloc() and fgets().

But better use dynamic reading:

#include "stdio.h"
#include "string.h"
#include "stdlib.h"

int main() {
  int mem = 64;
  char *str = malloc(mem);
  fgets(str, mem, stdin);
  while(str[strlen(str) - 1] != '\n') { //checks if we ran out of space
    mem *= 2;
    str = realloc(str, mem); //double the amount of space
    fgets(str + mem / 2 - 1, mem / 2 + 1, stdin); //read the rest (hopefully) of the line into the new space.
  }
  printf("%s", str);
}
Sign up to request clarification or add additional context in comments.

11 Comments

Whoa! That's utopian, except for how many times the loop runs, maybe. When I type printf("%s", str);, the code works, even my second version works(i changed app_len to app_len+1. I think something's wrong with the way I'm printing my output, like @Xephon and @DeepikaSethi said.
@yay Your code works only up to the length of 100. You are working really with a, only rename it to s. And memory that you gave to s, is lost. Memory leak!
Well, weirdly, the first variant works, but the second variant doesn't, and neither does the one you wrote. (I only give inputs less than 100 characters long). Am I allowed to post the rest of my program as well? I seriously have no idea where I'm going wrong.
It works now! I didn't do anything much. I'm not allowed to use string functions, so I wrote a function length()- int length(char *s) { int i; for(i=0;*(s+i)!='\0';i++); return i; } main() { int i, len;int mem = 64; char *s = malloc(mem); fgets(s, mem, stdin); while(s[length(s) - 1] != '\n') { mem *= 2; s = realloc(s, mem); fgets(s + mem / 2 - 1, mem / 2 + 1, stdin); } len=length(s); *(s+len--)='\0'; //rest of the code }
Well, it's the same thing you wrote except that I used int length(char *s) { int i; for(i=0;*(s+i)!='\0';i++); return i; } and then len=length(s); *(s+len--)='\0';
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.