In this line:
scanf("%s", &word[i]);
You need to make sure word[i] is pointing somewhere, and has enough space to occupy the string entered. Since word[i] is a char * pointer, you need to at some time allocate memory for this. Otherwise, it is just a dangling pointer not pointing anywhere.
If you want to stick with scanf(), then you can allocate some space beforehand with malloc.
malloc()allocates requested memory on the heap, then returns avoid*pointer at the end.
You can apply malloc() in your code like this:
size_t malloc_size = 100;
for (i = 0; i < 3; i++) {
word[i] = malloc(malloc_size * sizeof(char)); /* allocates 100 bytes */
printf("Enter word: ");
scanf("%99s", word[i]); /* Use %99s to avoid overflow */
/* No need to include & address, since word[i] is already a char* pointer */
}
Note: Must check return value of malloc(), because it can return NULL when unsuccessful.
Additionally, whenever you allocate memory with the use of malloc(), you must use free to deallocate requested memory at the end:
free(word[i]);
word[i] = NULL; /* safe to make sure pointer is no longer pointing anywhere */
Another approach without scanf
A more proper way to read strings should be with fgets.
char *fgets(char *str, int n, FILE *stream)reads a line from an input stream, and copies the bytes over tochar *str, which must be given a size ofnbytes as a threshold of space it can occupy.
Things to note about fgets:
- Appends
\ncharacter at the end of buffer. Can be removed easily. - On error, returns
NULL. If no characters are read, still returnsNULLat the end. - Buffer must be statically declared with a given size
n. - Reads specified stream. Either from
stdinorFILE *.
Here is an example of how it can be used to read a line of input from stdin:
char buffer[100]; /* statically declared buffer */
printf("Enter a string: ");
fgets(buffer, 100, stdin); /* read line of input into buffer. Needs error checking */
Example code with comments:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define NUMSTR 3
#define BUFFSIZE 100
int main(void) {
char *words[NUMSTR];
char buffer[BUFFSIZE];
size_t i, count = 0, slen; /* can replace size_t with int if you prefer */
/* loops only for three input strings */
for (i = 0; i < NUMSTR; i++) {
/* read input of one string, with error checking */
printf("Enter a word: ");
if (fgets(buffer, BUFFSIZE, stdin) == NULL) {
fprintf(stderr, "Error reading string into buffer.\n");
exit(EXIT_FAILURE);
}
/* removing newline from buffer, along with checking for overflow from buffer */
slen = strlen(buffer);
if (slen > 0) {
if (buffer[slen-1] == '\n') {
buffer[slen-1] = '\0';
} else {
printf("Exceeded buffer length of %d.\n", BUFFSIZE);
exit(EXIT_FAILURE);
}
}
/* checking if nothing was entered */
if (!*buffer) {
printf("No string entered.\n");
exit(EXIT_FAILURE);
}
/* allocate space for `words[i]` and null terminator */
words[count] = malloc(strlen(buffer)+1);
/* checking return of malloc, very good to do this */
if (!words[count]) {
printf("Cannot allocate memory for string.\n");
exit(EXIT_FAILURE);
}
/* if everything is fine, copy over into your array of pointers */
strcpy(words[count], buffer);
/* increment count, ready for next space in array */
count++;
}
/* reading input is finished, now time to print and free the strings */
printf("\nYour strings:\n");
for (i = 0; i < count; i++) {
printf("words[%zu] = %s\n", i, words[i]);
free(words[i]);
words[i] = NULL;
}
return 0;
}
Example input:
Enter a word: Hello
Enter a word: World
Enter a word: Woohoo
Output:
Your strings:
words[0] = Hello
words[1] = World
words[2] = Woohoo
Answer from RoadRunner on Stack OverflowIn this line:
scanf("%s", &word[i]);
You need to make sure word[i] is pointing somewhere, and has enough space to occupy the string entered. Since word[i] is a char * pointer, you need to at some time allocate memory for this. Otherwise, it is just a dangling pointer not pointing anywhere.
If you want to stick with scanf(), then you can allocate some space beforehand with malloc.
malloc()allocates requested memory on the heap, then returns avoid*pointer at the end.
You can apply malloc() in your code like this:
size_t malloc_size = 100;
for (i = 0; i < 3; i++) {
word[i] = malloc(malloc_size * sizeof(char)); /* allocates 100 bytes */
printf("Enter word: ");
scanf("%99s", word[i]); /* Use %99s to avoid overflow */
/* No need to include & address, since word[i] is already a char* pointer */
}
Note: Must check return value of malloc(), because it can return NULL when unsuccessful.
Additionally, whenever you allocate memory with the use of malloc(), you must use free to deallocate requested memory at the end:
free(word[i]);
word[i] = NULL; /* safe to make sure pointer is no longer pointing anywhere */
Another approach without scanf
A more proper way to read strings should be with fgets.
char *fgets(char *str, int n, FILE *stream)reads a line from an input stream, and copies the bytes over tochar *str, which must be given a size ofnbytes as a threshold of space it can occupy.
Things to note about fgets:
- Appends
\ncharacter at the end of buffer. Can be removed easily. - On error, returns
NULL. If no characters are read, still returnsNULLat the end. - Buffer must be statically declared with a given size
n. - Reads specified stream. Either from
stdinorFILE *.
Here is an example of how it can be used to read a line of input from stdin:
char buffer[100]; /* statically declared buffer */
printf("Enter a string: ");
fgets(buffer, 100, stdin); /* read line of input into buffer. Needs error checking */
Example code with comments:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define NUMSTR 3
#define BUFFSIZE 100
int main(void) {
char *words[NUMSTR];
char buffer[BUFFSIZE];
size_t i, count = 0, slen; /* can replace size_t with int if you prefer */
/* loops only for three input strings */
for (i = 0; i < NUMSTR; i++) {
/* read input of one string, with error checking */
printf("Enter a word: ");
if (fgets(buffer, BUFFSIZE, stdin) == NULL) {
fprintf(stderr, "Error reading string into buffer.\n");
exit(EXIT_FAILURE);
}
/* removing newline from buffer, along with checking for overflow from buffer */
slen = strlen(buffer);
if (slen > 0) {
if (buffer[slen-1] == '\n') {
buffer[slen-1] = '\0';
} else {
printf("Exceeded buffer length of %d.\n", BUFFSIZE);
exit(EXIT_FAILURE);
}
}
/* checking if nothing was entered */
if (!*buffer) {
printf("No string entered.\n");
exit(EXIT_FAILURE);
}
/* allocate space for `words[i]` and null terminator */
words[count] = malloc(strlen(buffer)+1);
/* checking return of malloc, very good to do this */
if (!words[count]) {
printf("Cannot allocate memory for string.\n");
exit(EXIT_FAILURE);
}
/* if everything is fine, copy over into your array of pointers */
strcpy(words[count], buffer);
/* increment count, ready for next space in array */
count++;
}
/* reading input is finished, now time to print and free the strings */
printf("\nYour strings:\n");
for (i = 0; i < count; i++) {
printf("words[%zu] = %s\n", i, words[i]);
free(words[i]);
words[i] = NULL;
}
return 0;
}
Example input:
Enter a word: Hello
Enter a word: World
Enter a word: Woohoo
Output:
Your strings:
words[0] = Hello
words[1] = World
words[2] = Woohoo
There seems to be a bit of confusion in this area. Your primary problem is you are attempting to write each word to the address of each of pointers you declare with char *word[3];. (not to mention you have no storage allocated at the location pointed to by each pointer -- but you never get there as you attempt to write to the address of each pointer with &word[i] rather than to the pointer itself)
While you can use scanf you will quickly run into one of the many pitfalls with taking user input with scanf that plague all new C programmers (e.g. failing to handle the '\n' left in the input buffer, failing to handle whitespace in strings, failing to limit the number of characters read/written, failing to validate the read or handle EOF, etc...)
A better approach is to simply use fgets and then trim the '\n' that fgets read and includes in the buffer to which it stores the string. A simple example would be:
#include <stdio.h>
#include <string.h>
#define NWDS 3 /* declare a constant for the maximum number of words */
int main (void) {
int i, n = 0;
char word[NWDS][50] = { "" }; /* provide storage or allocate */
for (i = 0; i < NWDS; i++) { /* for a max of NWDS */
printf ("Enter word : "); /* prompt */
if (!fgets (word[i], sizeof word[i], stdin)) /* read/validate */
break; /* protect against EOF */
size_t len = strlen (word[i]); /* get length */
if (word[i][len-1] == '\n') /* check for trailing '\n' */
word[i][--len] = 0; /* overwrite with nulbyte */
}
n = i; /* store number of words read */
putchar ('\n'); /* make it pretty */
for (i = 0; i < n; i++) /* output each word read */
printf (" word[%d] : %s\n", i, word[i]);
#if (defined _WIN32 || defined _WIN64)
getchar(); /* keep terminal open until keypress if on windows */
#endif
return 0;
}
Go ahead and cancel input at any time by generating an EOF during input (ctrl + d on Linux or ctrl + z on windoze), you are covered.
Example Use/Output
$ ./bin/wordsread
Enter word : first word
Enter word : next word
Enter word : last word
word[0] : first word
word[1] : next word
word[2] : last word
Looks things over, consider the other answers, and let me know if you have further questions.
Videos
Scanf() only accepts input for a single word.(not after space.)
To enter multiple words, you can use gets(string) or scanf("%[^\n]", string).
This - char[]listOfWords[9999]; is not a valid syntax to declare array.
You simply need to declare an array -
char s[100];
fgets(s,100,stdin); // take input and store it in s
And using strtok or sscanf you can extract separate words in different arrays .
Or you can use a 2-d array -
char s[100][100];
So if string stored in it is - Hello how are you guys
then by s[0] you will get Hello , s[1] will give how and similarly , other words in string.
Yes, but you need to make sure you have enough space to do so:
char input[3][50]; // enough space for 3 strings with
// a length of 50 (including \0)
fgets(&input[0], 50, stdin);
printf("Inputted string: %s\n", input[0]);
Using char **input does not have any space allocated for the input, therefore you cannot do it.
It's possible, but somewhat tedious, especially if you don't know the number of strings at the beginning.
char **input;
That much is fine. From there, you need allocate an array of (the right number of) pointers:
input = malloc(sizeof(char *) * MAX_LINES);
Then you need to allocate space for each line. Since you typically only want enough space for each string, you typically do something like this:
#define MAX_LINE_LEN 8192
static char buffer[MAX_LINE_LEN];
long current_line = 0;
while (fgets(buffer, sizeof(buffer), infile) && current_line < MAX_LINES) {
input[current_line] = malloc(strlen(buffer)+1);
strcpy(buffer[current_line++], buffer);
}
If you don't know the number of lines up-front, you typically allocate a number of pointers to start with (about as above), but as you read each line, check whether you've exceeded the current allocation, and if you have realloc the array of pointers to get more space.
If you want to badly enough, you can do the same with each individual line. Above, I've simply set a maximum that's large enough you probably won't exceed it very often with most typical text files. If you need it larger, it's pretty easy to expand that. At the same time, any number you pick will be an arbitrary limit. If you want to, you can read a chunk into your buffer, and if the last character in the string is not a new-line, keep reading more into the same string (and, again, use realloc to expand the allocation as needed). This isn't terribly difficult to do, but covering all the corner cases correctly can/does get tedious.
Edit: I should add that there's a rather different way to get the same basic effect. Read the entire content of the file into a single big buffer, then (typically) use strtok to break the buffer into lines (replacing "\n" with "\0") to build an array of pointers into the buffer. This typically improves speed somewhat (one big read instead of many one-line reads) as well as allocation overhead because you use one big allocation instead of many small ones. Each allocation will typically have a header, and get rounded to something like a (multiple of some) power of two. The effect of this varies with the line length involved. If you have a few long lines, it probably won't matter much. If you have a lot of short lines, it can save a lot.
The process is basically the same regardless of whether you read from stdin or read from a file. You either read each line with line-oriented input (fgets or getline) or you use character-oriented input (getchar, fgetc, etc). (the scanf family falls in the middle). When reading lines, generally the best choice is line-oriented input.
When reading user input into an array, you have two choices, either declare a static array of pointers and hope you allocated enough pointers to begin with, or you dynamically allocate the array of pointers and realloc as needed to hold all input. (who knows, the user might redirect a file for reading). When you allocate anything dynamically you are responsible to track its use, preserve a pointer to the original starting address for the block of memory, and freeing the memory when it is no longer needed.
The following is a standard example of taking input from stdin and storing it in a dynamically allocated array. There is a twist. The code can handle input from a file or stdin. If a filename is given as the first argument, then it will read the file, otherwise it reads from stdin. It expects the user to provide as much input as required, and then press [ctrl+d] when done. (manually generating EOF).
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define NMAX 128
int main (int argc, char **argv) {
char *ln = NULL; /* NULL forces getline to allocate */
size_t n = 0; /* initial ln size, getline decides */
ssize_t nchr = 0; /* number of chars actually read */
size_t idx = 0; /* array index counter */
size_t nmax = NMAX; /* check for reallocation */
char **array = NULL; /* array to hold lines read */
FILE *fp = NULL; /* file pointer to open file fn */
if (argc > 1) {
if (!(fp = fopen (argv[1], "r"))) {
fprintf (stderr, "error: file open failed for '%s'\n", argv[1]);
return 1;
}
}
else
fp = stdin;
/* allocate NMAX pointers to char* */
if (!(array = calloc (NMAX, sizeof *array))) {
fprintf (stderr, "error: memory allocation failed.");
return 1;
}
if (fp == stdin)
printf ("\nEnter information to store in array on each line, [ctrl+d] when done:\n\n");
/* read each line from file or stdin - dynamicallly allocated */
while ((nchr = getline (&ln, &n, fp)) != -1)
{
/* strip newline or carriage rtn */
while (nchr > 0 && (ln[nchr-1] == '\n' || ln[nchr-1] == '\r'))
ln[--nchr] = 0;
array[idx] = strdup (ln); /* allocate/copy ln to array */
idx++; /* increment value at index */
if (idx == nmax) { /* if lines exceed nmax, reallocate */
char **tmp = realloc (array, nmax * 2 * sizeof *tmp);
if (!tmp) {
fprintf (stderr, "error: memory exhausted.\n");
break;
}
array = tmp;
nmax *= 2;
}
}
if (ln) free (ln); /* free memory allocated by getline */
if (fp != stdin) fclose (fp); /* close open file descriptor */
size_t i = 0;
/* print array */
printf ("\nThe lines in the file are:\n\n");
for (i = 0; i < idx; i++)
printf (" line[%3zu] : %s\n", i, array[i]);
/* free array */
for (i = 0; i < idx; i++)
free (array[i]);
free (array);
return 0;
}
Example/Output
$ ./bin/getline_readstdin_dyn
Enter information to store in array on each line, [ctrl+d] when done:
This is a line of input
This is another
and another
etc..
The lines in the file are:
line[ 0] : This is a line of input
line[ 1] : This is another
line[ 2] : and another
line[ 3] : etc..
Or reading from a file:
$ ./bin/getline_readstdin_dyn dat/ll_replace_poem.txt
The lines in the file are:
line[ 0] : Eye have a spelling chequer,
line[ 1] : It came with my Pea Sea.
line[ 2] : It plane lee marks four my revue,
line[ 3] : Miss Steaks I can knot sea.
line[ 4] : Eye strike the quays and type a whirred,
line[ 5] : And weight four it two say,
line[ 6] : Weather eye am write oar wrong,
line[ 7] : It tells me straight aweigh.
line[ 8] : Eye ran this poem threw it,
line[ 9] : Your shore real glad two no.
line[ 10] : Its vary polished in its weigh.
line[ 11] : My chequer tolled me sew.
line[ 12] : A chequer is a bless thing,
line[ 13] : It freeze yew lodes of thyme.
line[ 14] : It helps me right all stiles of righting,
line[ 15] : And aides me when eye rime.
line[ 16] : Each frays come posed up on my screen,
line[ 17] : Eye trussed too bee a joule.
line[ 18] : The chequer pours over every word,
line[ 19] : Two cheque sum spelling rule.
Redirecting input is fine as well. E.g.:
$ ./bin/getline_readstdin_dyn < dat/ll_replace_poem.txt
At the risk of advising parse kludge, you have your read loop. Now use strtok or sscanf to parse string by tokens into storage variables. In this setup I suspect strdup is the better choice.
If you don't want to change the strings, then you could simply do
const char *a[2];
a[0] = "blah";
a[1] = "hmm";
When you do it like this you will allocate an array of two pointers to const char. These pointers will then be set to the addresses of the static strings "blah" and "hmm".
If you do want to be able to change the actual string content, the you have to do something like
char a[2][14];
strcpy(a[0], "blah");
strcpy(a[1], "hmm");
This will allocate two consecutive arrays of 14 chars each, after which the content of the static strings will be copied into them.
There are several ways to create an array of strings in C. If all the strings are going to be the same length (or at least have the same maximum length), you simply declare a 2-d array of char and assign as necessary:
char strs[NUMBER_OF_STRINGS][STRING_LENGTH+1];
...
strcpy(strs[0], aString); // where aString is either an array or pointer to char
strcpy(strs[1], "foo");
You can add a list of initializers as well:
char strs[NUMBER_OF_STRINGS][STRING_LENGTH+1] = {"foo", "bar", "bletch", ...};
This assumes the size and number of strings in the initializer match up with your array dimensions. In this case, the contents of each string literal (which is itself a zero-terminated array of char) are copied to the memory allocated to strs. The problem with this approach is the possibility of internal fragmentation; if you have 99 strings that are 5 characters or less, but 1 string that's 20 characters long, 99 strings are going to have at least 15 unused characters; that's a waste of space.
Instead of using a 2-d array of char, you can store a 1-d array of pointers to char:
char *strs[NUMBER_OF_STRINGS];
Note that in this case, you've only allocated memory to hold the pointers to the strings; the memory for the strings themselves must be allocated elsewhere (either as static arrays or by using malloc() or calloc()). You can use the initializer list like the earlier example:
char *strs[NUMBER_OF_STRINGS] = {"foo", "bar", "bletch", ...};
Instead of copying the contents of the string constants, you're simply storing the pointers to them. Note that string constants may not be writable; you can reassign the pointer, like so:
strs[i] = "bar";
strs[i] = "foo";
But you may not be able to change the string's contents; i.e.,
strs[i] = "bar";
strcpy(strs[i], "foo");
may not be allowed.
You can use malloc() to dynamically allocate the buffer for each string and copy to that buffer:
strs[i] = malloc(strlen("foo") + 1);
strcpy(strs[i], "foo");
BTW,
char (*a[2])[14];
Declares a as a 2-element array of pointers to 14-element arrays of char.
Use the strcpy function:
Instead of
newLsArray[i] = array;
write
strcpy(newLsArray[i], array);
When you define an array like char[10] his type is char [10] not char* and so array is of type char[10] while newLsArray[i] is of type char [sizeof(eachLineOfLsInArray) / sizeof(char)] which is different and so you get a type error, you can either use strcpy or work with pointers and malloc command and that way the line newLsArray[i] = array; would work.
To work with pointers you will need to define an array as char* and 2-d array as char** and malloc them accordingly.
That should read scanf("%s",names[i]);
Right now, you are storing it as scanf("%s",names);, which is equivalent to scanf("%s",names[0]);
So, you are overwriting that same array entry in every pass.
EDIT:
Also, when you pass char names[][] to a function, it only passes the pointer to the first element. You should declare atleast one bound of it, to the same value as the one to which you declared it.
int main(){
//To accept 2 names of 2 characters each
char names[2][2];// or char** names;
initialize(names, 2,2);
}
void initialize(char names[][2],const int MAX_NAMES,const int MAX_NAMELENGTH){ .. }
^ syntax error if index not present
(Reference)
You should store the name into a specific entry in the array:
scanf("%s", names[i]);
printf("%s\n", names[i]);
also few generic issues:
- capital names like MAX_NAMES are used in most cases for definitions and not for variables
- scanf is not a safe function as you cannot limit the amount of chars it reads and writes