• We’re currently investigating an issue related to the forum theme and styling that is impacting page layout and visual formatting. The problem has been identified, and we are actively working on a resolution. There is no impact to user data or functionality, this is strictly a front-end display issue. We’ll post an update once the fix has been deployed. Thanks for your patience while we get this sorted.

A few questions about Strings in C

L337Llama

Senior member
Hello, im writing a program that takes a command from the command prompt thats a file name and two dimensions, and then makes a maze of those dimensions in the file.

It's supposed to then take commands from stdin consisiting of a string and integers. I want to use scanf to take the input and put it as needed, so it'd look something like this:

scanf("%s %d %d %d %d", &str1, &int1, &int2, &int3, &int4);

I don't want to use a static array to hold the string, so I was wondering if I called Char str1[] with no indication to it's size, if it would automatically become big enough to hold the %s. Also, I want to see how many successful items are put in place with the scanf,

so itd look like
intSuccess = scanf("%s %d %d %d %d", &str1, &int1, &int2, &int3, &int4);

Would doing that make a new instance of scanf to recieve stuff? Or would i need to use something like
char bufferStr[100];

gets(&bufferStr);
sscanf(bufferStr, "%s %d %d %d %d", &str1, &int1, &int2, &int3, &int4);
intSuccess = sscanf(bufferStr,"%s %d %d %d %d", &str1, &int1, &int2, &int3, &int4);
 
I don't want to use a static array to hold the string, so I was wondering if I called Char str1[] with no indication to it's size, if it would automatically become big enough to hold the %s.

No. In fact that declaration is illegal unless you include initializer syntax that tells the compiler how long the array is.

There is no support for strings in C. Just arrays of chars. They are dumb memory buffers, and you have to manage every aspect of their lifecycle.

You might also want to rethink using scanf as you've outlined, if only for the reason that it will be highly dependent on the user typing the right things in the right order at the prompt.
 
Ah, thanks. The input order is guaranteed, but the integers put are not gaurenteed to be the right dimensions, so it will check them against the maximum. I guess now I need to figure out how to dynamically alter the length of the string depending on whats called in scanf. I think I can write it to the buffer string and then use the strlen to make a new str and copy the buffer stuff into it. So, would using intSuccess = scanf("%s %d %d %d %d", &str1, &int1, &int2, &int3, &int4); like that run scanf and save the results to the variables specified, and also save the count of how many were saved?
 
You don't necessarily need to alter the string dynamically. Just make sure it is null-terminated in the proper place and big enough to accomodate the longest set of commands.
 
Is there a way to get the %s from scanf to be placed into a char[] that has it's size determined by how long the %s is.
 
Originally posted by: L337Llama
Is there a way to get the %s from scanf to be placed into a char[] that has it's size determined by how long the %s is.

I don't know of any way to do that. C is not a very "do things for you" type of language. You have to pretty much manage things yourself.

If you were really concerned with having it exactly the right size, you could reduce the size immediately afterwards.

I must agree with Markbnj though that using scanf in the way you're suggesting is not wise. You say that the input order is guaranteed, but lesson #23 in software coding: what the user can mess up they will eventually. It might be better to take them directly from the command line (char **argv) or ask for the seperately.

Also, try for more descriptive variable names than "str1" and "int2". They might make perfect sense in a tiny program, but getting into the habit of choosing descriptive names for everything will really help as your coding gets more complex. I will have to use the same names below though as I"m not sure where you're going with this code.

If separately, consider the following (I apoligize for the formatting - leading spaces get clipped out):

#include <string.h>
#include <stdio.h>

int main (int argc, char **argv) {
char *inputBuffer, *str1;
int int1, int2, int3, int4;

inputBuffer = (char *) malloc(sizeof(char) * 128);

// note that here by limiting the input length of the fgets to 128 chars, we prevent the possibility of a buffer overflow
printf("Enter string: ");
fgets (inputBuffer, 128, stdin);

// due to malloc'ing just as much space as the previous string's length (plus 1 char for the terminator)
// we keep the memory used lower
str1 = (char *) malloc(sizeof(char) * (strlen(inputBuffer) + 1));
strcpy (str1, inputBuffer);

printf("Enter number 1: ");
fgets (inputBuffer, 128, stdin);
int1 = atoi(inputBuffer);


printf("Enter number 2: ");
fgets (inputBuffer, 128, stdin);
int2 = atoi(inputBuffer);

printf("Enter number 3: ");
fgets (inputBuffer, 128, stdin);
int3 = atoi(inputBuffer);

printf("Enter number 4: ");
fgets (inputBuffer, 128, stdin);
int4 = atoi(inputBuffer);

free(inputBuffer);

/* do what you will with the values here */

free(str1);

return 0;
}



(when asking for the numbers you'll probably want to reduce the # of valid digits a little lower, but I'm not sure what ranges you're working within)
 
Originally posted by: L337Llama
Is there a way to get the %s from scanf to be placed into a char[] that has it's size determined by how long the %s is.
No, you cannot use scanf securely like this (you have to use a preallocated buffer and the user can probably always put in something bigger than the buffer). I would read the whole line in using fgetln, null terminate it and then use something like strsep to replace all the spaces with null, keeping a pointer to the head of each substring (and make sure to handle multiple spaces in a row). Then, parse ints out of the 2-5th strings, if they were found.

My c-foo is weak though. I bet there's an easier, pre-canned way to take a string and hack it into a set of substrings based on a separating character like a space.
 
I would just pass the parameters on the command line. Or if I really had to read input from the keyboard I would prompt the user for individual values one at a time.
 
Code:
#include <stdio.h>

char *gets(char *s){
   int c;
   char *dest = s;
   while ((c = getchar()) != '\n' && c != EOF)
       *dest++ = c;
    *dest++ = '\0';
   if (c == EOF)
       return NULL;
  return s;
}

int main(){
    char buf[256];
    gets(buf);
   
   // function to parse or search buf for what you want. strcmp, strstr, atoi, etc...

return 0;
}
 
You guys are a bunch of pessimists ;-)

There is a way to have the memory auto-malloc'ed -- use the a conversion specifier on the %s. Check out man scanf. Its just not ANSI-C, so it might not be around on all C platforms...
 
Originally posted by: degibson
You guys are a bunch of pessimists ;-)

There is a way to have the memory auto-malloc'ed -- use the a conversion specifier on the %s. Check out man scanf. Its just not ANSI-C, so it might not be around on all C platforms...

That's scanf for the truly lazy 🙂. Now, with Somnolent-C, never allocate stack memory for character arrays again! What implementation actually supports that? I just popped around to a few sites and it isn't mentioned.
 
I checked the man pages of a couple of the distros to which I have ready access, in relation to the 'a' conversion specifier. I found no mention of 'a' on centos4, and found this on RHEL5:
From man scanf on RHEL5:
This is a GNU extension; C99 employs the 'a' character as a conversion specifier (and it can
also be used as such in the GNU implementation).

Edit: Not shown, it goes on to explain that, yes, 'a' allocates memory and the caller is responsible for free()ing it.
 
Originally posted by: degibson
I checked the man pages of a couple of the distros to which I have ready access, in relation to the 'a' conversion specifier. I found no mention of 'a' on centos4, and found this on RHEL5:
From man scanf on RHEL5:
This is a GNU extension; C99 employs the 'a' character as a conversion specifier (and it can
also be used as such in the GNU implementation).

Edit: Not shown, it goes on to explain that, yes, 'a' allocates memory and the caller is responsible for free()ing it.

You start coding to platform extensions that are not ANSI standard, you take the chance that the code will not work properly on another platform or compile/build properly

 
Originally posted by: Common Courtesy
Originally posted by: degibson
I checked the man pages of a couple of the distros to which I have ready access, in relation to the 'a' conversion specifier. I found no mention of 'a' on centos4, and found this on RHEL5:
From man scanf on RHEL5:
This is a GNU extension; C99 employs the 'a' character as a conversion specifier (and it can
also be used as such in the GNU implementation).

Edit: Not shown, it goes on to explain that, yes, 'a' allocates memory and the caller is responsible for free()ing it.

You start coding to platform extensions that are not ANSI standard, you take the chance that the code will not work properly on another platform or compile/build properly

:laugh:
 
Back
Top