C multidimensional array pointing problem? - c

Trying to take strings as input and place it in 2d array. Why is this given code showing different behavior. The last for loop "arr[i][j]" is not printing the string.It is not even printing a character also.
Why this code does not work.only this code.Not a new way to write it
This code takes input just fine(or at least the way needed.each row a single string no white space)And when a short string is stored remaining are filled with null after carriage return. When the arr[] is passed in last for loop everything seems fine only when arr[][] is passed ,the problem arises.But again arr[][] is initialized as arr[1][0] then arr[2][0] so should not it work!
#include <stdio.h>
#include <stdbool.h>
int main(void){
int i,j,m;
scanf("%d",&m);
char arr[m][50];
for(i=0;i<m;i++){
for(j=0;j<50;j++){
printf("please enter a string");
scanf("%s",&arr[i][j]);
/*j is always 0. arr[i] takes string without space and store ending with null*/
break;
}
}
//Everything fine upto this,including storing a small continuous string in arr[i](where i<50) and null terminating*/
for(i=0;i<m;i++){
for(j=0;j<50;j++){
printf("%s\n",arr[i][j]);
break;
}
}
}

You program has several issues, like using wrong format specifier:
scanf("%s",&arr[i][j]);
arr[i][j] is a character and you are using %s format specifier. If you want your program should take string as input, you just need to do:
scanf("%s",arr[i]);
Since, you have given the size 50 characters, put a restriction in scanf() to not to read more than 49 characters (the remain one character space is for null terminating character) like this:
scanf("%49s",arr[i]);
^^
Beware with this, it does not discard the remaining input from input stream when the input characters are more than 49 and the remaining characters will be consumed by consecutive scanf() call.
If you want to drop the extra input which wasn't consumed by scanf(), one way of doing it is to read and discard the extra input using a loop, like this:
int c;
while((c = getchar()) != '\n' && c != EOF)
/* discard the character */;
In case if you have any doubt on how this will discard the extra input, I would suggest first go through getchar().
Putting all these together, you can do:
#include <stdio.h>
int main(void){
int i,m;
scanf("%d",&m);
char arr[m][50];
for(i=0;i<m;i++){
printf("please enter a string");
scanf("%49s",arr[i]);
int c;
while((c = getchar()) != '\n' && c != EOF) // <=== This loop read the extra input characters and discard them
/* discard the character */;
}
for(i=0;i<m;i++){
printf("%s\n",arr[i]);
}
return 0;
}
EDIT
The below edit is because OP updated question and added - Why this code does not work.only this code.Not a new way to write it
Above in my answer, I have already stated that you are using wrong format specifier in the scanf(). In this part of your code:
for(i=0;i<m;i++){
for(j=0;j<50;j++){ // <====== Nested for loop
printf("please enter a string");
scanf("%s",&arr[i][j]);
// since the nested loop is supposed to run 50 times, assuming you are trying to read character by character and using %s format specifier
break;
// the nested loop will break in the first iteration itself unconditionally, do you really need nested loop here!
}
}
Check the inline comments. Hope this might give an idea of the mistakes you are doing.
Seems that you want to read string character by character using scanf(). If this is the case than make sure to take care of null terminating character because, in C, strings are actually one-dimensional array of characters terminated by a null character '\0'.
You can do:
#include <stdio.h>
void discard_extra_input() {
int c;
while((c = getchar()) != '\n' && c != EOF)
/* discard the character */;
}
int main(void){
int i,j,m;
printf ("Enter number of strings: ");
scanf("%d",&m);
discard_extra_input();
char arr[m][50];
for(i=0;i<m;i++){
printf("please enter string number %d: ", i+1);
for(j=0;j<49;j++){
scanf("%c",&arr[i][j]);
if (arr[i][j] == '\n') {
//need to add null terminating character manually
arr[i][j] = '\0';
break;
}
}
if (j==49) {
// In case where the input from user is more than 50 characters,
// need to add null terminating character manually.
arr[i][j] = '\0';
// discard the extra input when input from user is more than 50 characters.
discard_extra_input();
}
}
for(i=0;i<m;i++){
for(j=0;j<50 && arr[i][j]!='\0';j++){
printf("%c",arr[i][j]);
}
printf ("\n");
}
return 0;
}
The code is self explanatory except one thing - call to discard_extra_input() function after first input from user scanf("%d",&m);. Reason -
Look at the statement:
scanf("%c",&arr[i][j]);
the %c format specifier will consume the leftover newline character '\n' from the input stream due to the ENTER key pressed after first input by the user (number of strings input from user). Hence, in order to discard it, calling discard_extra_input() function. In the other place it has been used to discard the characters when user entered string of size more than 49.
Hope this helps.

I know the code. But looking for specific ans. Where the problem lies with the code
The problem is here:
scanf("%s",&arr[i][j]);
and here:
printf("%s", arr[i][j]);
This is the specific answer you are looking for.
%s won't do any bound checking. It adds the characters starting from the memory location arr + i * m + j to arr + i * m + j + (length of input) + 1 (one extra char for the additional null character that scanf appends). Take a sample input. Assume an arbitrary starting address for arr and do the maths.
Also consider any writes beyond the allocated space for arr leads to undefined behavior.
Similarly printf("%s", arr[i][j]); will try to start reading from the address arr[i][j] till it finds a null character. It would usually lead to crash of the code because if your string has ascii characters, the address would be too low to point to any valid user-mapped memory.
If your code is working, its mostly because you already have a UB in your scanf.
Get a pen and paper and do some dry runs

This is a pretty simple problem buddy. You've got the idea right actually, that you need to use 2d array to store strings. Just that the usage is slightly wrong.
First of all let me tell you how 2d arrays need to be used to store in c. In your 2-D array, you've got rows and columns. Say, row represented by i and columns by j, i.e, each row arr[i] contains j elements. So in your context, each row arr[i] contains each string of upto 50 chars. So scanf should be just for arr[i]. And you need to loop with for, m times to accept m strings.
Same applies to printing as well.
Here is the working code:
#include <stdio.h>
#include <stdbool.h>
int main(void){
int i,j,m;
printf("\nenter m value:");
scanf("%d",&m);
char arr[m][50];
for(i=0;i<m;i++){
printf("\nplease enter a string no %d: ", (i+1));
scanf("%s",arr[i]);
}
printf("\nthe strings are: \n");
for(i=0;i<m;i++){
printf("\n%s\n",arr[i]);
}
}
And the output in case you want to cross check:
OUTPUT:
enter m value: 3
please enter a string no 1: qwerty
please enter a string no 2: asdfgh
please enter a string no 3: zxcvbn
the strings are:
qwerty
asdfgh
zxcvbn

Related

Count the amount of occurrences of a character in a string: how can I interpret this code?

The assignment asks to print out the number of times a chosen character appears in an input (no length limit) string. I wanted to solve it by only using do or do-while loops, and after a bit of googling I found this code (source: https://www.tutorialgateway.org/c-program-to-count-all-occurrence-of-a-character-in-a-string/.).
I get the gist of it, but there are many things I still haven't covered, such as the meaning of str[i], the meaning of the variable ch, and kind of how the structure works. How can I interpret it piece by piece? Or if there's any simpler way, how can I work on it? I'm a beginner and I fear this is much easier than expected but I don't have the base to move on, thank you
#include <stdio.h>
#include <string.h>
int main() {
char str[10], ch;
int i, Count;
i = Count = 0;
printf("\n Please Enter any String : ");
gets(str);
printf("\n Please Enter the Character that you want to Search for : ");
scanf("%c", &ch);
while (str[i] != '\0') {
if (str[i] == ch) {
Count++;
}
i++;
}
printf("\n The Total Number of times '%c' has Occurred = %d ", ch, Count);
return 0;
}
Well i am giving an easy example regarding that problem with a proper explanation. Hope you might understand.
char is a datatype which will accepts character type of variable. Here str[100] will be an array of length 100, where we will store our search example. ch is a character type variable where we will store the character for which we will find the concurrence.
i and count are integer variables where i will be loop variable and the count will keep count of the concurrence.
after taking the text string using puts function we are storing it in the str[100] array.
then we are taking the search letter and stored it in ch.
we are now running for loop from 0 to the length of the string we have given.
strlen() function returning us the length.
now str[i] will search from i=0 to the length size of the string. each time loop will go forward one by one letter and compare the letter with the letter inside ch.
if match found then we will increase the count value.
after the ending of the loop count will be the result of the concurrency.
reference: Concurrency of a letter in a string
#include <stdio.h>
#include <string.h>
int main()
{
char str[100], ch;
int i, Count;
Count = 0;
printf("\n Please Enter any String : ");
gets(str);
printf("\n Please Enter the Character that you want to Search for : ");
scanf("%c", &ch);
for(i = 0; i <= strlen(str); i++)
{
if(str[i] == ch)
{
Count++;
}
}
printf("\n The Total Number of times '%c' has Occured = %d ", ch, Count);
return 0;
}
The code has the following parts:
1)The header files: These contain predefined functions like scanf() which you use in your program
2)The main function: Here you are performing your character count. Usually, this function contains the driver code for the program
ch is a variable for the character you want to count in your string. You are taking this as input from the user using scanf()
str is the string you are performing your count operation in. It is also taken as input.
str[i] is used to denote the index i in the string. For example in "test", the index of 's' will be 2 as it is the 3rd character and your index starts from 0.
Final note: I recommend going through the basic syntax and usage of arrays if you do not know indexing. Also, as someone commented, do not use gets(). It causes security issues in programs as user can access stack values by giving malicious inputs containing format specifiers.
Instead, use a scanf with proper format specifiers or use fgets() when accessing content from files.

Output didn't include all of the characters

I was trying to input a string of characters and only output the last and the first character respectively. Below is the code I'm using.
#include<stdio.h>
int main(){
for(int i=0;i<3;i++){
int n; // length of the string
char string[101];
scanf("%d %s", &n, &string);
fflush(stdin); // sometimes I also use getchar();
printf("%c%c", string[n+1], string[0]);
}
printf("\n");
return 0;
}
I'm using for loop because i wanted to input the string 3 times, but when I ran the code the input isn't what I expected. If I input e.g.
5 abcde
output
a //there's space before the a
can you help me tell where I've gone wrong?
input:
5 abcde
6 qwerty
3 ijk
excpeted output:
ea
yq
ki
Few problems in your code:
In this statement
scanf("%d %s", &n, &string);
you don't need to give & operator with string. An array name, when used in an expression, converts to pointer to first element (there are few exceptions to this rule). Also, the size of string array is 101 characters but if you provide input more than 101 characters, the scanf() end up accessing string array beyond its size. You should restrict the scanf() to not to read more than 100 characters in string array when input size is more than that. (keep the remain one character space is for null terminating character that scanf() adds). For this, you can provide width modifier in the format specifier - %100s.
You are not validating the string length input against the input string from user. What happen, if the input string length is greater than or less than the actual length of input string!
fflush(stdin) is undefined behaviour because, as per standard, fflush can only be used with output streams.
I was trying to input a string of characters and only output the last and the first character respectively.
For this, you don't need to take the length of the string as input from user. Use standard library function - strlen(). This will also prevent your program from the problems that can occur due to erroneous length input from user, if that is not validated properly.
Putting these altogether, you can do:
#include <stdio.h>
#include <string.h>
int main (void) {
for (int i = 0; i < 3 ; i++) {
char string[101];
printf ("Enter string:\n");
scanf("%100s", string);
printf("Last character: %c, First character: %c\n", string[strlen(string) - 1], string[0]);
int c;
/*discard the extra characters, if any*/
/*For e.g. if user input is very long this will discard the input beyond 100 characters */
while((c = getchar()) != '\n' && c != EOF)
/* discard the character */;
}
return 0;
}
Note that, scanf(%<width>s, ......) reads up to width or until the first whitespace character, whichever appears first. If you want to include the spaces in input, you can use the appropriate conversion specifier in scanf() or a better alternative is to use fgets() for input from user.
Line 11: string[n+1] -> string[n-1]

Taking strings as a 2-D char array

I want a code such that I enter some strings one-by-one (by pressing enter) and display it.
for example;
Input
abc
def
Output
abc
def
also I want this input to be in a array so that I can select any character
from the array whenever I want. For example: s[1][1] gives 'e'.
I have writen a code for this problem.
#include <stdio.h>
#include <stdlib.h>
int main()
{
int i, j, n, m;
scanf("%d%d", &n, &m);
char a[n][m];
for (i = 0; i<n; i++)
scanf("%s", a[i]);
for (i = 0; i<n; i++) {
printf("%s", a[i]);
printf("\n");
}
}
But for this code my input/output goes like this:
Input
ab
cd
Output
abcd
cd
Can anyone tell where am I going wrong?
You have not shown the input value of n and m in the question. But from the input and output string shown, it seems that char array a[i] does not have the enough space for terminating null-character \0. When you give format specifier %s, scanf() automatically adds a terminating null character at the end of the stored sequence. I tried your code with input 2 for both n and m and I am getting the output as you are getting:
$ ./a.out
2 2
ab
cd
abcd
cd
Give the value 4 to m and the output is:
2 4
ab
cd
ab
cd
When using scanf() for string input, it is good to add check for max character modifier that is 1 less than the length of the input buffer. So, if the size of input buffer is 4 then you can do
scanf("%3s",a[i]);
With this, the scanf() will read not more than 3 characters in a[i] and will add \0 at the fourth location of a[i]. Beware with this, it does not discard the remaining input from input stream and they will be consumed by consecutive scanf() call.
If you want to drop the extra input which wasn't consumed by scanf, one way of doing it is to read and discard the extra input using a loop, like this:
int c;
while((c = getchar()) != '\n' && c != EOF)
/* discard the character */;
You can add it after scanf() reads data from input stream, like this:
for(i=0; i<n; i++) {
scanf("%3s", a[i]); // assuming the size of a[i] is 4
int c;
while((c = getchar()) != '\n' && c != EOF) // <=== This loop read the extra input characters and discard them
/* discard the character */;
}
This will work fine for the input that does not contain any whitespace characters. If your input contain any whitespace character, it may not behave as expected. Hence, I would suggest you to read about fgets() which gives you better control for string input.
Check this: fgets
and this: How to read from stdin with fgets()?
you are working with a 2D array of char:
char a[n][m];
but keep in mind the value for the 2nd index should be 1 character longer than the length of the string you wish it to allow room for the \0 byte. (all C strings must be null terminated)
This means char a[n][m]; can contain up to n strings, each string with maximum length of m-1 bytes.
char exampleStr[] = {"char count"}; //for example contains 11 characters (not 10)
|c|h|a|r| |c|o|u|n|t|\0| //note nul char is appended
Another common problem when reading user input in a loop is failure to remove any unwanted newlines, which can cause the loop to behave poorly. Following is an example of how to read a user specified number of strings ( using fgets() instead of scanf() ), each with a user specified length: (also removing unwanted newlines ( \n ) in the process)
For readability, the following example replaces n & m with lines & maxLen.
int main(void)
{
int lines, maxLen, i=0;
printf("Enter number of lines:");
scanf(" %d", &lines);
printf("Enter maxLen line length:");
scanf(" %d", &maxLen);
char line[lines][maxLen+2]; //+2 to allow for trailing newline and null
fgets(line[i], maxLen, stdin);//consume anything left in stdout
printf("Enter up to %d characters and hit return:\n%d) ", maxLen, i+1);
for(i=0;i<(lines);i++)
{
fgets(line[i], maxLen, stdin);
line[i][strcspn(line[i], "\n")] = 0; // clear newline
printf("Enter up to %d characters and hit return:\n%d) ", maxLen, i+1);
}
return 0;
}
All strings in C must be terminated with the null character \0, print knows this and prints all character UP TO that sign. You should make all of your strings 1 character longer than the words you plan to fit in them and fill them with 0 (0 is the integer value of \0) in the start to avoid this problem.

Allocating Memory to String at runtime

I am writing a program to count the occurrence of '2' followed by '1' in a sting.
I dynamically allocated string
Code is:
#include <stdio.h>
#include<stdlib.h>
int penalty_shoot(char* s){
int count=0,i=0;
while(s[i]!='\0'){
if(s[i]=='2')
if(s[i+1]=='1')
count++;
i++;
}
return count;
}
int main() {
int t;
int i=0;
scanf("%d",&t); //t is for number of test cases.
while(t--){
char *str, c;
str = (char*)malloc(1*sizeof(char));
while(c = getc(stdin),c!='\n')
{
str[i] = c;
i++;
str=realloc(str,i*sizeof(char));
}
str[i] ='\0';
printf("%s\n",str);
printf("%d\n",penalty_shoot(str));
free(str);
str=NULL;
i=0;
}
return 0;
}
Input is :
3
101201212110
10101
2120
I am facing 2 problems:
1) I feel the dynamic allocation is not working fine.I wrote the code for dynamic allocation seeing various codes on stackoverflow . (Can anyone suggest some changes.)
2) The code isn't reading '2120' as the 3rd input.
(why is it so ?)
Three errors:
Not checking for EOF:
Change while(c = getc(stdin),c!='\n') to while(c=getc(stdin),c!='\n'&&c!=EOF)
Reallocating with the wrong number of bytes:
Change str=realloc(str,i*sizeof(char)); to str=realloc(str,(i+1)*sizeof(char));
After taking one character input we increment i (i++), so the next character will be stored at the ith position. Now, in order to store the character at ith position, the length of the character array must be i+1. So, we realloc with i+1.
Just for the sake of brevity, as suggested by Basile, you
might as well do this:
Change str=realloc(str,(i+1)*sizeof(char)); to str=realloc(str,i+1);
Why? Because sizeof char is 1 byte
Not consuming the \n after inputting t:
Change scanf("%d",&t); to scanf("%d ",&t); or scanf("%d\n",&t);
scanf("%d ",&t); or scanf("%d\n",&t);.
Either of them works. Why, you ask? Read this explanation taken from another SO answer here:
An \n - or any whitespace character - in the format string consumes
an entire (possibly empty) sequence of whitespace characters in the
input. So the scanf only returns when it encounters the next
non-whitespace character, or the end of the input stream.
Tested here.
you can use scanf("%d ", &t); when user input to test
then just before second while loop, which condition should be c != '\n' write c = getchar();
and then make sure you create a char variable, i called mine clear, that receives 0 so when you loop after initiating your string you write c = clear; and under it c = getchar() again. and when you use realloc make sure you make it bigger by (i+1) since char is only the size of 1 byte.
we create the clear variable in order to clear the buffer.
it worked for me. make sure you insert the string all at once.

Incorrect output, simple strings exercise - C

I am trying to write a function that gets a string of letters, either capital letters or small letters, and prints 2 other strings, one with only the capitals, and one only with the small letters. for example:
input: AaBbCcDD
Output: Capital string is ABCDD, non capital is abc
My code is not working correctly, it seems to skip over the last letter. To test it, I wrote the following code:
int length;
printf("Please enter length of string\n");
scanf("%d",&length);
string=create_string(length);
scan_string(string,length);
printf("The string entered is: \n");
print_string(string,length);
Where create_string is:
char* create_string(int size)
{
char* string;
string=(char*)malloc(size*sizeof(char));
return string;
}
Scan string is:
void scan_string(char* string, int size)
{
int i;
printf("Please enter %d characters\n",size);
for(i=0;i<size;i++)
scanf("%c",string+i);
}
And print string is
void print_string(char* string,int size)
{
int i;
for(i=0;i<size;i++)
printf("%c ",*(string+i));
}
When I try even just to print the string I entered, this is what I get, after I input aaAAB
The output is a a A A.
it skipped over the B.
The problem is with the scanf that reads characters using %c: it follows the scanf that reads the length using %d, which leaves an extra '\n' character in the buffer before the first character that you get.
If you modify the output to put quotes around your characters, you would actually see the \n:
void print_string(char* string,int size)
{
int i;
for(i=0;i<size;i++)
printf("'%c' ",*(string+i));
}
This prints
'
' 'a' 'a' 'A' 'A'
(demo on ideone)
You can change your first scanf to read '\n' as below. This will read the extra '\n'
scanf("%d\n", &length);
I think your code is unnecessarily elaborated. To read a string the function fget() with parameter stdin is a simpler choice.
For example, I wuold not ask to the user for the length of the string.
Perhaps it is better to use a buffer with fixed length, and to restrit the user to enter a string with the length less than which you have been previously stipulated.
#define MAXLEN 1000
char buffer[MAXLEN] = "";
fgets(buffer, MAXLEN, stdin);
If the user attempts to enter a string with more than MAXLEN characters, it would be necessary to handle the end-of-line in some way, but I think this is out of topic.
So, in general, let us suppose that MAXLEN is large enough such that buffer contains the \n mark.
Now, a call to your function print_string() can be done.
However, it would be better to do this:
printf("%s", buffer);
I think that you probably need to take in account the C convention for strings: a string is a char array whose last element is marked with the character '\0' (null character, having always code 0).
Even if you want to insist in your approach, I think that scanf() is a bad choice to read individual characters. it is more easy to use getchar(), instead.
By using scanf() you have to broke your brain figurating out all the stuff around the behaviour of scanf(), or how to handle the read of characters, and so on.
However, getchar() reads one char at a time, and that's (almost) all. (Actually, the console commonly not returns the control to the user until an end-of-line \n has been read).
string[i] = getchar();
The problem is because the scanf does not eat the "\n". Hence there is still one '\n' remaining at your first input. This will be counted at the next scanf.
Try to put an additional getchar() right after your first scanf.
printf("Please enter length of string\n");
scanf("%d",&length);
getchar(); // remove '\n'
string=create_string(length);

Resources