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
As mentioned in comments, you must change this:
/* bad */
int score [n];
printf("Number of scores: ");
scanf("%d", &n);
into this
/* good */
printf("Number of scores: ");
scanf("%d", &n);
int score [n];
This since C executes code from top to bottom like when you are reading a book. It will not "double back" a few rows above and fill in n once it has been entered by the user. At the point where you declare int score [n], n must already be known.
If your using an array with unknown size during compilation, I would suggest using memory allocation. So the user determines the array size while running the program.
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
int n, i;
int *score;
printf("Number of scores: ");
scanf("%d", &n);
score = (int *)malloc(sizeof(int)*n);
for(i=0; i<n; i++){
printf("score: ");
scanf("%d", &score[i]);
}
free(score)
return 0;
}
The malloc function allocates memory with the size of n and returns a pointer to the allocated memory.
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
Working on some problems for school and I cannot figure out I am supposed to do this.
The problem at hand:
Ask the user to input two series of 10 integers. They can be double or single digits.
Turn them in to arrays and check if any of the values match.
I've seen suggestions online about setting each input to a char but wouldn't that include the spaces?
The only way I've been able to do this is to set it up where the user inputs a number, hits enter, rinse and repeat.
That's real simple. But I can't figure out how to take random spaces and numbers and fit them nearly into arrays.
I've been trying to figure this out for a while now. I'm trying to user input strings into an array. I started out in Java, and would do it this way.
System.out.print("how many names will you enter? ");
int length = input.nextInt();
int counter = 0;
String[] names = new String[length];
for (String i: names){
names[counter] = input.next();
counter++;
if (counter == names.length){
input.close();
int counter1 = 0;
for (String i1: names){
System.out.printf("the string in index %d is '%s'\n", counter1,i1);
counter1++; } } }In C, I can do this, but only with numbers. I have tried with for loops and while loops. I have googled it, but it seems that the only way to do it is an advanced way/requires more C programming knowledge and I basically don't understand what is happening when I see the example code.
This is my latest attempt. I can enter one string then after I enter the second one, it says the string i entered 'is not a valid command'
char *states[20];
int num_states = 4;
for(int i = 0; i < num_states; i++) {
scanf("%s", states[i]);
}
for(int i = 0; i < num_states; i++) {
printf("state %d: %s\n", i, states[i]);
}Any way to do it similar to the Java way? Or must I have a deeper understanding of the C language?
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.
Hi I have a task that currently seems impossible to me. I have to write a program which takes a string input from a user and determines its length. I am supposed to not use the library functions (such as strlen) to determine the length and I cant use the array index operator [].
I know about the relationship between arrays and pointers, but I have no clue how I can declare an array using only pointers. Once I declare the array I can iterate over it with a for loop without using brackets like this:
*(array + i)
The rest of the program is also no issue, its just that I don't know how to declare the array and let a user input a string without array brackets.
I read about some solutions on stackoverflow that use malloc or typedef, but unfortunately I am still a beginner that just started the pointer topic and don't know what these are. I am pretty sure that these are advanced topics and the task is supposed to be solvable without using them.
Thank you for your help!
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.
This is your immediate problem:
scanf("\n %c", str1);
This format string tells scanf to read some amount of whitespace followed by a single character, which is to be stored in str1.
@H2CO3 is right: scanf is almost never the right answer for reading input from the user. It performs no bounds checking and is too finicky about the format of user input; one unexpected character will completely confuse it. You are very strongly encouraged to use fgets instead if at all possible:
fgets(str1, 100, stdin);
If you are not allowed to do this, you should ask your professor why not. Seriously.
If you absolutely must use scanf to read input here, you can do it the way @user2479209 described in their answer.
There is another problem with your program, which is that toupper(chars[i]) will not change the value stored in chars[i]. You have to assign the result of toupper back to the array explicitly, e.g.:
chars[i] = toupper(chars[i]);
change str1 and str2 to array. use %100[^\n] in first two scanf's.It's a regular expression trick to read strings with spaces.read about it.
char str1[101];
char str2[101];
scanf("%100[^\n]",str1);
scanf("%100[^\n]",str2);
This will take in two strings.hit enter after entering the first string to enter the second.
Some dialects of C have variable-length arrays (VLA), notably C99 (and GCC accepts them....)
But your teacher probably wants you to understand C dynamic memory allocation, and you should also test when scanf fails, so you might code:
int main(void) {
int size, i;
printf("Enter the size of the arrays:\n");
if (scanf("%d", &size)<1) {
perror("scan size");
exit(EXIT_FAILURE);
};
Actually, you'll better test against the case of size being negative! I leave that up to you.
int *arr1 = calloc(size, sizeof(int));
if (arr1==NULL) {
perror("calloc arr1");
exit(EXIT_FAILURE);
}
You always need to handle failure of calloc or malloc
printf("Enter the elements of the array:\n");
for (i = 0; i < size; i++) {
if(scanf("%d", &arr1[size])<1) {
perror("scanf arr1[size]");
exit(EXIT_FAILURE);
}
}
scanf_s is only existing in C11, and on a C11 compliant implementation you could use VLAs
I leave the rest up to you. You want to code a for loop to print every element of the array.
Of course you should call free appropriately (and I am leaving that to you). Otherwise, you have a memory leak. Some systems have valgrind to help hunting them. Don't forget to compile with all warnings & debug info (with GCC use gcc -Wall -g) then use the debugger (e.g. gdb).
Don't forget that a programming language is a specification (written in some document), not a software. You may want to glance into n1570. And you need to understand what undefined behavior means.
You can't use static memory allocation to allocate an array with a dynamic size. You'll need to dynamically request memory to be allocated to your program, by the operating system, of whatever dynamic size the use asks for.
Here's an example to get started:
#include <stdlib.h>
#include <stdio.h>
void printArray(int *array, int size) {
// Sample array: [1, 2, 3, 4, 5]
printf("["); // [
for (int i = 0; i < size - 1; i++) { // [1, 2, 3, 4,
printf("%i, ", array[i]);
}
if (size >= 1) printf("%i", array[size-1]); // [1, 2, 3, 4, 5
printf("]\n"); // [1, 2, 3, 4, 5]
}
int main(void) {
int count;
printf("Enter the size of the array:\n");
scanf("%d", &count);
// ask for enough memory to fit `count` elements,
// each having the size of an `int`
int *array = malloc(count * sizeof(*array));
if (!array) {
printf("There was a problem with malloc.");
exit(EXIT_FAILURE);
}
printf("Enter the elements of the array:\n");
for (int i = 0; i < count; i++) scanf("%d", &array[i]);
printArray(array, count);
//do stuff
free(array);
}
For the %c specifier, scanf needs the address of the location into which the character is to be stored, but printf needs the value of the character, not its address. In C, an array decays into a pointer to the first element of the array when referenced. So, the scanf is being passed the address of the first element of the name array, which is where the character will be stored; however, the printf is also being passed the address, which is wrong. The printf should be like this:
printf("%c", name[0]);
Note that the scanf argument is technically ok, it is a little weird to be passing an array, when a pointer to a single character would suffice. It would be better to declare a single character and pass its address explicitly:
char c;
scanf("%c", &c);
printf("%c", c);
On the other hand, if you were trying to read a string instead of a single character, then you should be using %s instead of %c.
Either Read a single char
char name[2];
scanf("%c",name);
printf("%c",name[0]);
Or read a string
char name[2];
scanf("%1s",name);
printf("%s",name);