Click here to Skip to main content
15,879,326 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
#include<stdio.h>
#include<stdlib.h>

int main()
{
    int i, types;
    i=0;
    printf("how many types/categories of meds you want?\n");
    scanf(" %d", &types);
    printf(" %d", types);
    char * category[types];

       printf("\nPlease mention the categories of meds like B.P, anxiety, blood thinners,etc:\n\n");

    while( i<types)
       {
         category[i]= malloc(30 * sizeof(char));
         printf("CATEGORY #%d ?\n\n",i+1);
         gets(category);
         getchar();
         i++;
       }

     for ( i=0; i< types ;i++)
     {
         printf(" %s",category[i]);
     }


    return 0;
}


What I have tried:

I have used heap memory but can someone explain why this doesnt work and solution for it?
Posted
Updated 6-Nov-22 4:27am
Comments
CHill60 3-Nov-22 6:59am    
What inputs did you use? What were you expecting to be output? What actually happens?
Sharyar Javaid 3-Nov-22 7:04am    
well.. its clearly evident in the code. its part of a bigger code but it doesnt work here so no point going on.. I input medicines category but doesnt work.
CHill60 3-Nov-22 8:18am    
If your inputs were "clearly evident" in the code then I would not have asked the question. Your code is not going to explain what actually happened either. Asking questions is an art - vagueness will only delay any solutions
Sharyar Javaid 4-Nov-22 2:58am    
There is only 1 string input in the code that's why I said what I said. dont take it personally. it is clearly evident in the code my friend
CHill60 4-Nov-22 3:22am    
I can see the variables in your code but I cannot see what you typed on your keyboard when prompted.
By the way, you are wrong...there is one integer input and there are a variable number of string inputs, the exact number depending on what you typed in response to the first prompt.
I'm not taking anything personally - it's not me looking for help but if it was I would be including all relevant information in my question - you did not.

I couldn't get this to work at all using gets - in fact I got a compiler warning telling me not to use it. However, the syntax for gets is
C
char *gets(char *str)
and you are passing it a char **str

Try replacing
gets(category);
with
scanf("%s", category[i]);
 
Share this answer
 
Comments
Sharyar Javaid 4-Nov-22 3:03am    
thanks for the answer! but scanf doesn't input spaces. how to tackle that?
CHill60 4-Nov-22 3:17am    
It worked for me
merano99 6-Nov-22 3:12am    
Never use scanf with %s, because buffer overflows are not preventable.
My suggestion would be fgets, even if it is not a 100% replacement.
NOTE: The function gets() is no longer available in C or C++ (as of C11 & C++14)
Alternatives are discussed e.g. here
https://stackoverflow.com/questions/43174201/alternative-to-gets
CHill60 6-Nov-22 4:34am    
Good point. Virtual 5
merano99 6-Nov-22 11:28am    
See Solution 4 for my version.
Try
C
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

#define CHARS 30

int main()
{
  int c, categories;
  printf("how many types/categories of meds you want?\n");
  scanf(" %d", &categories);
  printf(" %d", categories);
  char * category[categories];

  printf("\nPlease mention the categories of meds like B.P, anxiety, blood thinners,etc:\n\n");



  for( c = 0; c < categories; ++c)
  {
    unsigned long len = 0;
    category[c]= malloc(CHARS * sizeof(char));
    printf("CATEGORY #%d ?\n\n", (c+1));

    while (len < 2)
    {
      fgets(category[c], CHARS, stdin);
      len = strlen(category[c]);
    }
  }

  for ( c = 0; c < categories ; ++c)
    printf(" %s", category[c]);

  for ( c = 0; c < categories; ++c)
    free(category[c]);

  return 0;
}
 
Share this answer
 
Comments
Sharyar Javaid 5-Nov-22 6:31am    
it works.. but can you please explain what have you done in the while loop? also what is unsigned long is doing? thanks
CPallini 5-Nov-22 7:17am    
I am reading and discarding the newlines left by scanf in the stdin buffer.
An unsigned long is used to retrieve the return value of strlen (size_t would have been more appropriate).
merano99 6-Nov-22 3:18am    
You should not fill the buffer completely with fgets() and hope that strlen() finds an end of string. I would recommend to keep the last byte free for a 0.
You have two problems:
1 the use of scanf to read values will leave a line end in the input buffer, which causes the next input command to read the wrong data. You need to clear the buffer after the call to scanf:
C++
char dummy[4];
gets(dummy);

2. You are missing the offset for the buffer address when you read the medicine details:
C++
gets(category); // should be          gets(category[i]);
 
Share this answer
 
Comments
merano99 6-Nov-22 3:22am    
+5
Richard MacCutchan 6-Nov-22 3:39am    
Thanks. It really beats me why they are still teaching scanf in colleges.
merano99 6-Nov-22 8:40am    
Unfortunately gets() has been removed in the meantime for a good reason. It has the same problems as scanf() with %s. there are alternatives like fgets() or better C++ and getline().
Richard MacCutchan 6-Nov-22 10:58am    
"gets() has been removed"
No, it's still there in Microsoft C.

"It has the same problems as scanf() with %s."
No, because it does not use format specifiers.
merano99 6-Nov-22 11:53am    
I can't use it with Visual-Studio and the doc says it's gone.
https://learn.microsoft.com/en-us/cpp/c-runtime-library/gets-getws
With problem I meant the not limitable length.
As Richard has already correctly pointed out, this line does not work:
C
gets(category);

Here you want to read in several lines. But the command obviously always overwrites the same place, and one that is not intended for that.

The gets() function has since been removed from C and C++ for good reason. There are almost the same problems as with scanf() with %s, since the string length cannot be limited. An alternative that reads only to the end of the line and at the same time respects the buffer size does not exist under C. If it absolutely must be C it becomes somewhat more complex, since one must write the desired function.

As said before, a function to read in a line with a limited buffer would have to be written by yourself if necessary:
C
int mygetline(char *buf, size_t len)
{
	char ch;
	for (int k = 0; (k <= len); ) {
		ch = getchar();
		if ((ch != '\r') && (ch != '\n')) {
			buf[k] = ch;
			k++;
		}
		else if (k>0) break;
	}
	if (ch != '\n') {
		while (ch = getchar() != '\n');  // delete rest of line
		return 1;
	}
	else
		return 0;
}

Note: With C++ you could use getline() as an alternative.

When inserted into the (corrected) original program, it looks like this:
C
printf("Please mention the %d categories:\n", types);
for (i=0; i<types; i++) {
	category[i] = (char*)calloc(types, (MAX_LINELEN + 1) * sizeof(char));
	if (category[i] == NULL) 
		break;

	printf("CATEGORY #%d:\n", i + 1);
	mygetline(category[i], MAX_LINELEN);
}
 
Share this answer
 
v8
Comments
Sharyar Javaid 6-Nov-22 14:30pm    
thanks. can you list resources where you've learnt all this? I am currently only learning from "absolute beginner's guide to C by Greg Perry". I have 2/3rd of the book finished but these technical problems havent been shared in detailed.
merano99 6-Nov-22 15:08pm    
I needed almost no special knowledge for this and I wonder how to comment "learned all this". For C, the book by Kerninghan & Ritchie (second edition) is enough to start with. However, it doesn't deal with the brand new features of C, but you can learn them later. In addition, you get experience by programming yourself and reading in forums ... I don't know the book "Absolute Beginner's Guide to C by Greg Perry", but if you can't do anything with loops and termination conditions after 2/3 of the book, I would find it questionable.
Sharyar Javaid 6-Nov-22 14:44pm    
also if you have time can you please explain what are you doing in the separate function with the conditions and loops. I have studied functions and recursions for basic maths like finding factorial, etc but this function's logic is hard to grasp for me
merano99 6-Nov-22 15:18pm    
The function mygetline() reads individual characters until either the end of the line is reached or the end of the buffer. For this the loop for (int k = 0; (k <= len); ) with the index k is run through. If the line is finished and not empty it is terminated with break. A line that has not been read completely is then deleted up to the end of line character. If the line was read completely, 0 is returned otherwise 1. It makes sense to look at the whole thing line by line with a debugger.
Sharyar Javaid 6-Nov-22 15:30pm    
still thanks for the solution

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900