C: Size of array changes scanf - c

I'm trying to understand, why does the size of array change the output (input is 10 5). If I set char k[1] then it only prints 5, but if I set char k[2] then if prints 10 5.
This is my code:
#include <stdio.h>
#include <string.h>
int main() {
char n[10 ^ 1000];
char k[1];
scanf("%s%s", n, k);
for (int i = 0; i < strlen(n); i++) {
printf("%d", n[i] - '0');
}
printf(" %d", k[0] - '0');
}

In this declaration
char n[10^1000];
there is used the bitwise exclusive OR operator ^.
From the C Standard (6.5.11 Bitwise exclusive OR operator)
4 The result of the ^ operator is the bitwise exclusive OR of the
operands (that is, each bit in the result is set if and only if
exactly one of the corresponding bits in the converted operands is
set).
So the above declaration is equivalent to
char n[994];
When a string is entered using the conversion specifier s then the function scanf stores also the terminating zero character '\0' in the destination character array.
As a result for this declaration
char k[1];
where there is no space for the terminating zero character '\0' the call of scanf overwrites memory beyond the array that results in undefined behavior.
As for your question then it is seems that the compiler placed the character array n just after the array k. So the terminating zero character is written in the first character of the array n when the array k is declared as shown above with one element and after the call of scanf you have in fact in the memory occupied by the arrays the following
k[0] = '5';
n[0] = '\0';
That is the array n stores an empty string.

As coded, your program has undefined behavior because char k[1] defines an array of size 1, which can only receive an empty string, which scanf("%s"...) cannot parse. The string typed will cause a buffer overflow: scanf() will attempt to store bytes beyond the end of the destination array.
You must pass the maxumum number of characters to store into the destination array before the null terminator.
Also note that 10^1000 used the xor operator and has the value 994.
To output the ASCII values of the characters typed, just pass the char values directly with the format %d, they will be promoted to int implicitly:
#include <stdio.h>
#include <string.h>
int main() {
char s[100];
if (scanf("%99s", s) == 1) {
for (int i = 0; s[i] != '\0'; i++) {
printf("char at offset %d is `%c` (ASCII %d)\n", i, s[i], s[i]);
}
}
return 0;
}

#include <stdio.h>
#include <string.h>
int main()
{
char n[5];
char k[5];
int i;
printf("input for char n is = ");
scanf("%s", n);
printf("input for char k is = ");
scanf("%s", k);
for (i=0; i<strlen(n); i++)
{
printf("char n is = ");
printf("%d \n", n[i] -'0');
}
printf("char k is = ");
printf("%d \n", k[0] - '0');
}
// "for" loop initial declaration are allowed only on c99 or c11 mode.

Related

I want to make program in C printing each number of full number

#include <stdio.h>
int main() {
char a[1000];
int i = 0;
scanf("%s", &a);
while (a[i] != 0) {
printf("%c\n", a[i]);
i++;
}
printf("\n");
return 0;
}
"A large integer of up to 1,000 digits is given as input. Write a program that prints out each digit of the integer after receiving the corresponding integer." was the problem and I don't know what is not complete in my code. I got 4/5 point. answer have to be like:
Input: +456
Output:
+
4
5
6
Your code has two issues:
1.
scanf("%s", &a);
The argument a already decays to a pointer to the first element of array a -> so the type of it as argument is actually char *. Thus, &a is of type char (*)[1000].
There is a type mismatch to the expected argument of type char * for the %s conversion specifier.
If you use GCC as compiler, the -Wall option (or respectively -Wformat=) had showed you a warning about this:
warning: format '%s' expects argument of type 'char *', but argument 2 has type 'char (*)[1000]' [-Wformat=]
9 | scanf("%s",&a);
| ~^ ~~
| | |
| | char (*)[1000]
| char *
2.
Furthermore, if you need to store an integral number up to 1000 digits - which includes the case of a 1000 digit integer, you forgot that you need one element more to store the string-terminating null character ('\0'):
char a[1001];
Else, if the user inputs a number of 1000 digits, the null character would be stored beyond the bounds of the array, which invokes undefined behavior.
Additionally:
Use a length modifer to ensure there will occur no buffer overflow if the user attempts to enter a number of more than 1000 digits:
scanf("%1000s", a);
or use fgets() which is ensures this by default as it requires the number of characters to be written as second argument.
fgets(a, sizeof(a), stdin);
sizeof(a) is appropriate as sizeof(char) is always 1. It obtains the number of elements, a has.
Result:
#include <stdio.h>
int main (void) {
char a[1001];
int i = 0;
printf("Please enter an integral number up to 1000: ");
fgets(a, sizeof(a), stdin);
// scanf("%1000s", a); Alternative to previous fgets.
while (a[i] != 0) {
printf("%c\n", a[i]);
i++;
}
printf("\n");
return 0;
}
scanf("%s",&a);
Should change to:
scanf("%999s",a);
or you can use fgets from stdin instead:
fgets(a, 1000, stdin);
see Disadvantages of scanf
There are multiple problems in your code:
the size of the array is too small, it can only contain up to 999 digits.
the scanf() format should specify the maximum number of characters to store into the destination array to avoid undefined behavior on overlong input.
the scanf() argument &a is incorrect, it should be just a.
the return value of scanf() should be tested to avoid undefined behavior on an empty input file.
Here is a corrected version:
#include <stdio.h>
int main() {
char a[1002]; /* sign + 1000 digits + null terminator */
if (scanf("%1001s", a) == 1) {
for (int i = 0; a[i] != '\0'; i++) {
printf("%c\n", a[i]);
}
printf("\n");
} else {
printf("error: no input\n");
}
return 0;
}
Ma'am,
String in c always end with a null character i.e, '\0' not just 0.
replace this "while(a[i]!=0)" with "while(a[i]!='\0')"..
and everything ll be cool..:-)
Going by your requirement, scanf will take 'a' not '&a'. Also the loop will continue till the end, which is denoted by '\0' character and not zero.
#include <stdio.h>
int main(){
char a[1000];
int i=0;
scanf("%s", a);
while(a[i]!='\0')
{
printf("%c\n",a[i]);
i++;
}
printf("\n");
return 0;
}

How to count the number of same character in C?

I'm writing a code a that prompts the user to enter a string
&
create a function that is a type void that prints out the character that was used the most
(As in where it appeared more than any other ones)
&
also shows the number of how many times it was in that string.
Therefore here is what I have so far...
#include <stdio.h>
#include <string.h>
/* frequent character in the string along with the length of the string (use strlen from string.h – this will require you to #include <string.h> at the top of your program).*/
/* Use array syntax (e.g. array[5]) to access the elements of your array.
* Write a program that prompts a user to input a string,
* accepts the string as input, and outputs the most
* You should implement a function called mostfrequent.
* The function prototype for mostfrequent is: void mostfrequent(int *counts, char *most_freq, int *qty_most_freq, int num_counts);
* Hint: Consider the integer value of the ASCII characters and how the offsets can be translated to ints.
* Assume the user inputs only the characters a through z (all lowercase, no spaces).
*/
void mostfrequent(int *counts, char *most_freq, int *qty_most_freq, int num_counts_)
{
int array[255] = {0}; // initialize all elements to 0
int i, index;
for(i = 0; most_freq[i] != 0; i++)
{
++array[most_freq[i]];
}
// Find the letter that was used the most
qty_most_freq = array[0];
for(i = 0; most_freq[i] != 0; i++)
{
if(array[most_freq[i]] > qty_most_freq)
{
qty_most_freq = array[most_freq[i]];
counts = i;
}
num_counts_++;
}
printf("The most frequent character was: '%c' with %d occurances \n", most_freq[index], counts);
printf("%d characters were used \n", num_counts_);
}
int main()
{
char array[5];
printf("Enter a string ");
scanf("%s", array);
int count = sizeof(array);
mostfrequent(count , array, 0, 0);
return 0;
}
I'm getting the wrong output too.
output:
Enter a string hello
The most frequent character was: 'h' with 2 occurances
5 characters were used
should be
The most frequent character was: 'l' with 2 occurances
5 characters were used
let's do it short (others will correct me if I write something wrong ^_^ )
you declare a int like this:
int var;
use it like this :
var = 3;
you declare a pointer like this :
int* pvar;
and use the pointed value like this:
*pvar = 3;
if you declared a variable and need to pass a pointer to it as function parameters, use the & operator like this :
functionA(&var);
or simply save its address in a pointer var :
pvar = &var;
that's the basics. I hope it will help...
The function prototype you are supposed to use seems to include at least one superfluous parameter. (you have the total character count available in main()). In order to find the most frequently appearing character (at least the 1st of the characters that occur that number of times), all you need to provide your function is:
the character string to be evaluated;
an array sized so that each element represents on in the range of values you want to find the most frequent (for ASCII characters 128 is fine, for all in the range of unsigned char, 256 will do); and finally
a pointer to return the index in your frequency array that holds the index to the most frequently used character (or the 1st character of a set if more than one are used that same number of times).
In your function, your goal is to loop over each character in your string. In the frequency array (that you have initialized all zero), you will map each character to an element in the frequency array and increment the value at that element each time the character is encountered. For example for "hello", you would increment:
frequency['h']++;
frequency['e']++;
frequency['l']++;
frequency['l']++;
frequency['o']++;
Above you can see when you are done, the element frequency['l']; will hold the value of 2. So when you are done you just loop over all elements in frequency and find the index for the element that holds the largest value.
if (frequency[i] > frequency[most])
most = i;
(which is also why you will get the first of all characters that appear that number of times. If you change to >= you will get the last of that set of characters. Also, in your character count you ignore the 6th character, the '\n', which is fine for single-line input, but for multi-line input you need to consider how you want to handle that)
In your case, putting it altogether, you could do something similar to:
#include <stdio.h>
#include <ctype.h>
enum { CHARS = 255, MAXC = 1024 }; /* constants used below */
void mostfrequent (const char *s, int *c, int *most)
{
for (; *s; s++) /* loop over each char, fill c, set most index */
if (isalpha (*s) && ++c[(int)*s] > c[*most])
*most = *s;
}
int main (void) {
char buf[MAXC];
int c[CHARS] = {0}, n = 0, ndx;
/* read all chars into buf up to MAXC-1 chars */
while (n < MAXC-1 && (buf[n] = getchar()) != '\n' && buf[n] != EOF)
n++;
buf[n] = 0; /* nul-terminate buf */
mostfrequent (buf, c, &ndx); /* fill c with most freq, set index */
printf ("most frequent char: %c (occurs %d times, %d chars used)\n",
ndx, c[ndx], n);
}
(note: by using isalpha() in the comparison it will handle both upper/lower case characters, you can adjust as desired by simply checking upper/lower case or just converting all characters to one case or another)
Example Use/Output
$ echo "hello" | ./bin/mostfreqchar3
most frequent char: l (occurs 2 times, 5 chars used)
(note: if you use "heello", you will still receive "most frequent char: e (occurs 2 times, 6 chars used)" due to 'e' being the first of two character that are seen the same number of times)
There are many ways to handle frequency problems, but in essence they all work in the same manner. With ASCII characters, you can capture both the most frequent character and the number of times it occurs in a single array of int and an int holding the index to where the max occurs. (you don't really need the index either -- it just save looping to find it each time it is needed).
For more complex types, you will generally use a simple struct to hold the count and the object. For example if you were looking for the most frequent word, you would generally use a struct such as:
struct wfreq {
char *word;
int count;
}
Then you simply use an array of struct wfreq in the same way you are using your array of int here. Look things over and let me know if you have further questions.
Here is what I came up with. I messed up with the pointers.
void mostfrequent(int *counts, char *most_freq, int *qty_most_freq, int num_counts_)
{
*qty_most_freq = counts[0];
*most_freq = 'a';
int i;
for(i = 0; i < num_counts_; i++)
{
if(counts[i] > *qty_most_freq)
{
*qty_most_freq = counts[i];
*most_freq = 'a' + i;
}
}
}
/* char string[80]
* read in string
* int counts[26]; // histogram
* zero counts (zero the array)
* look at each character in string and update the histogram
*/
int main()
{
int i;
int num_chars = 26;
int counts[num_chars];
char string[100];
/*zero out the counts array */
for(i = 0; i < num_chars; i++)
{
counts[i] = 0;
}
printf("Enter a string ");
scanf("%s", string);
for(i = 0; i < strlen(string); i++)
{
counts[(string[i] - 'a')]++;
}
int qty_most_freq;
char most_freq;
mostfrequent(counts , &most_freq, &qty_most_freq, num_chars);
printf("The most frequent character was: '%c' with %d occurances \n", most_freq, qty_most_freq);
printf("%d characters were used \n", strlen(string));
return 0;
}

Garbage characters are printed forcefully [duplicate]

This question already has answers here:
Why do we need to add a '\0' (null) at the end of a character array in C?
(9 answers)
Closed 4 years ago.
This is a program that's supposed to read inputs, a number 'n' and a character, and then duplicate this character n times. It works perfectly fine, but when I enter a large number, 8+ for example, it duplicates perfectly but then adds garbage values to the end. I can't get why it does that since I used malloc and I have exactly n blocks saved for me in the memory.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char* create_string (char ch, int n);
void main ()
{
int n;
char ch;
printf("Enter number for duplicates: ");
scanf("%d",&n);
printf("Enter a letter: ");
scanf(" %c", &ch);
printf("The letter '%c' duplicated %d times is: ",ch,n);
char* ptr=create_string(ch,n);
printf("%s",ptr);
}
char* create_string (char ch, int n)
{
char* dup=(char*)malloc(n*sizeof(char));
int i;
for (i=0; i<n; i++)
{
dup[i]=ch;
}
return dup;
}
Test run:
Strings in C are as simple as null-terminated character sequences. That means whenever you create a string by hand, you must always append a '\0' at the end so other functions like printf know where it ends:
char* create_string (char ch, int n)
{
char* dup = malloc((n+1) * sizeof(char));
int i;
for (i=0; i<n; i++)
{
dup[i]=ch;
}
// This is important
dup[n] = '\0';
return dup;
}
Another subtle thing to notice is that because you need to store that terminating null character, you also need to reserve the space for it. So the malloc line is changed into:
malloc((n+1)*sizeof(char))
// ^^^^^ it's no longer 'n'
On a side note, you don't need to cast the returned pointer of malloc.
Strings in C are char arrays where the character \0 denotes the end of the string. Since you aren't explicitly adding it, printf just prints values from memory until it happens to run in to a terminating character (i.e., this is undefined-behavior). Instead, you should explicitly add this character to your result string:
char* create_string (char ch, int n)
{
char* dup = (char*) malloc((n + 1) * sizeof(char));
/* Added 1 for the '\0' char ---^ */
int i;
for (i = 0; i < n; i++)
{
dup[i]=ch;
}
/* Set the terminating char */
dup[n] = '\0';
return dup;
}

Converting string to number in C

I'm trying to write a program which converts lower cased alphabet to numerical digits.
a -> 01
b -> 02
...
z -> 26
For the first nine letters I need to put a 0 before the number.
This is my code.
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define MAXLEN 128
void s2n(char str[])
{
int i;
char x;
char result[256];
for (i=0; str[i] != '\0'; i++) {
x = str[i];
x = x - 96;
if (x < 10) {
char src[2] = {0, x};
strcat(result, src);
}
else {
char src2[1] = {x};
strcat(result, src2);
}
printf("%s", result);
}
}
int main(void)
{
char str[MAXLEN];
printf("Lower cased string please: ", MAXLEN);
scanf("%s", str);
s2n(str);
return 0;
}
Could you tell me what is wrong with my code??
One problem I see is:
char src[2] = {0, x};
You want to use the character 0, rather than the byte value 0 (NUL):
char src[2] = {'0', x};
Also, you need to NUL terminate your src array:
char src[] = {'0', x, 0};
The NUL termination would need to be done in both cases.
Another problem is your x = x - 96 statement also does not take into account that the character 0 is different from the byte value 0. So
x = x - 96 + '0';
would be better.
You use strcat() on an uninitialized array, result, it doesn't work that way, strcat() looks for the terminating nul byte in it's first parameter, and glues the second parameter from that point.
In your case there is no '\0' in result, calling strcat() with result as the first parameter causes undefined behavior.
You should at least ensure that there is one '\0' in result, you can do that by just setting the first element of result to '\0', like
result[0] = '\0';
Right before the loop starts, also you pass the second paramter src which is an array but is not a string, because it has no terminating '\0', but you actually don't need an array nor strcat().
You can use an index variable and just assing the ith element of the array to the actual character computed from the original value, like
result[i] = x;
Then you don't nul terminate result, which causes undefined behavior when you try to print resutl.
You also passing a parameter to printf() where it's not expecting one, that indicates that you are either silencing or ignoring compiler warnings.
There are many problems in your code, the following code, does what you want
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void s2n(char chr)
{
char result[4];
if (snprintf(result, sizeof(result), "%02d", 1 + chr - 'a') >= sizeof(result))
return;
printf("%s", result);
}
int main(void)
{
char chr;
printf("Lower cased string please: ");
if (scanf(" %c", &chr) != 1)
{
fprintf(stderr, "input error!\n");
return -1;
}
s2n(chr);
return 0;
}
note that no strings are required except the one where you are going to store the result, which you can build easily with sprintf().

Would does this function which converts a char array to an int array not work?

This program is supposed to convert the array of chars (string) into an array of ints by subtracting 97 from their ascii value (the input should be lower case cause a has an ascii value of 97). So if i enter the string abcd i should get 0123 but instead I somehow get this: 012134513789. I can't figure out where the problem is.
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
void userEnter(int*pattern, int n);
int main(void)
{
int n, i;
printf("What is the length of the array: ");
scanf("%d",&n);
int pattern[n];
printf("Enter the char array: ");
userEnter(pattern, n);
printf("The int array is: ");
for(i=0;i<n;i++)
{
printf("%d",pattern[i]);
}
printf("\n");
}
void userEnter(int*pattern, int n)
{
char input[n];
scanf("%s", input);
int i;
for(i = 0; i < n-1; i++)
{
pattern[i] = input[i]-97;
}
}
char input[n];
scanf("%s", &input);
should be
char input[n+1];
scanf("%s", input);
input is equivalent to &input[0]
You should also exit the for loop in userEnter when you encounter the nul character that ends the user-entered string. e.g. with something like
char* p = input;
while (*p != '\0') {
*pattern = (*p) - 'a';
p++;
pattern++;
}
As KingsIndian points out, you also need to increase the size of your input buffer. At present, you overflow that buffer and overwrite the loop counter i;
The length parameter n includes one character for null as well. So, if you input length for n 4 then you can only input 3 characters, for example abc because the 4th is for the null.
So you should change the declaration accordingly:
Change:
char input[n];
to:
char input[n+1];
Note that variable length arrays are allowed only since C99.

Resources