i am new to c programming. The value of the code needs to be 0 after the loop but it changes. Please help someone.
#include<stdio.h>
#include<string.h>
int main(void)
{
int n, i, k, j, sum;
char input[] = "";
scanf("%d", &n);
sum = 0;
for (i = 0; i< n; i++)
{
scanf("%s", &input[i]);
//sum = sum + (input[i]-48);
}
printf("%d", sum);
}
When you declare an array but leave the size blank, it is sized to exactly fit what it is initialized with.
In this case you initialize it with an empty string which is 1 byte long (for the terminating null character) so the array is only 1 character wide. So if you attempt to read any nonempty string into this variable you'll write past the bounds of the array. Doing so invokes undefined behavior.
As a start, make the array at least as large as you expect the input to be, for example:
char input[80];
Then read the string once, limiting the input to the size of the array minus 1, then loop through the values:
scanf("%79s", input);
for (i = 0; i< n; i++)
{
sum = sum + (input[i]-48);
}
Related
So, I was writing this code for counting the digit frequency i.e. the number of times the digits from 0-9 has appeared in a user inputted string(alphanumeric). So, I took the string, converted into integer and tried to store the frequency in "count" and print it but when I run the code, count is never getting incremented and the output comes all 0s. Would be grateful if anyone points out in which part my logic went wrong.
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <stdlib.h>
int main() {
// takes string input
char *s;
s = malloc(1024 * sizeof(char));
scanf("%[^\n]", s);
s = realloc(s, strlen(s) + 1);
//turns the string to int
int x = atoi(s);
int temp = x, len = 0;
//calculates string length
while (x != 0) {
x = x / 10;
len++;
}
x = temp;
//parses through the string and matches digits with each number
for (int j = 0; j < 10; j++){
int count = 0;
for(int i = 0; i < len; i++){
if(x % 10 == j){
count++;
}
x = x / 10;
}
x = temp;
printf("%d ", count);
}
return 0;
}
To write a correct and reasonable digit-counting program:
Do not allocate any buffer for this.
Create an array to count the number of times each digit occurs. The array should have ten elements, one for each digit.
Initialize the array to zero in each element.
In a loop, read one character at a time.
Leave the loop when the read routine (such as getchar) indicates end-of-file or a problem, or, if desired, returns a new-line or other character you wish to use as an end-of-input indication.
Inside the loop, check whether the character read is a digit. If the character read is a digit, increment the corresponding element of the array.
After the loop, execute a new loop to iterate through the digits.
Inside that loop, for each digit, print the count from the array element for that digit.
Your approach is way to complicated for a very easy task. This will do:
void numberOfDigits(const char *s, int hist[10]) {
while(*s) {
if(isdigit(*s))
hist[*s - '0']++;
s++;
}
}
It can be used like this:
int main(void) {
char buf[1024];
int hist[10];
fgets(buf, sizeof buf, stdin);
numberOfDigits(s, hist);
for(int i=0; i<10; i++)
printf("Digit %d occurs %d times\n", i, hist[i]);
}
This can also be quite easily achieved without a buffer if desired:
int ch;
int hist[10];
while((ch = getchar()) != EOF) {
if(isdigit(ch))
hist[ch - '0']++;
}
#include <stdio.h>
int main(void) {
int input = 1223330;
int freq[10] = {0};
input = abs(input);
while(input)
{
freq[input%10]++;
input /= 10;
}
for(int i=0; i<10; ++i)
{
printf("%d: %.*s\n", i, freq[i], "*************************************************");
}
return 0;
}
Output:
Success #stdin #stdout 0s 5668KB
0: *
1: *
2: **
3: ***
4:
5:
6:
7:
8:
9:
This app is currently limited by the size of an int (approximately 9 or 10 digits).
You can update it to use a long long easily, which will get you to about 19 digits.
I'm new at C and I'm trying to do an exercise which asks to insert some strings and then store them. First it requests a multidimensional array where we have for every row of the array a string, and then as an array of pointers.
Here's the code for the first part. I don't know how to store into an array some strings that are not already written.
For the second one I have no idea since I've never done exercises with pointers before.
#include <stdio.h>
int main(){
int n; //number of strings
int x; //number of characters per string
printf("How many strings do you want to insert?");
scanf("%d", &n);
if ((n >= 1) && (n <= 20)){
printf("How many characters per string?");
scanf("%d", &x);
char str[x];
if (x <= 10){
for(int i = 0; i < n; i++){
printf("Insert a string:");
scanf("%s", str);
for(int j = 0; j < x; j++){
char arr[j];
arr[j] = str[x];
printf("%s", arr);
}
}
}
else {
printf("Error:the number of characters must be < 10");
}
}
else {
printf("Error: the number must be < 20");
}
return 0;
}
... requests a multidimensional array where we have for every row of the array a string, and then as an array of pointers.
After getting the qualified number of strings, allocate an array of pointers to char.
if ((n >= 1) && (n <= 20)){
char **string_list = calloc(n, sizeof *string_list);
assert(string_list); // or other error checking
(Notice no type in = calloc(n, sizeof *string_list);. Easier to code right, review and maintain.)
Read the strings in a working temp buffer. As "How many characters per string?" likely means the number of characters not including the null character, our str[] needs a +1 in size.
// char str[x]; // too small
char str[x+1];
Yet we know x <= 10 and can use a fixed buffer size and limit input length
for(int i = 0; i < n; i++){
char str[10+1];
printf("Insert a string:");
scanf("%10s", str); // Notice the 10 - a width limit
// TBD check if scanf() returned 1 and if str is longer than x
Now allocate a copy of the str
string_list[j] = strdup(str);
assert(string_list[j]); // or other error checking
}
Later, when done with string_list[], clean-up and free allocations.
for (int i=0; i<n; i++) {
free(string_list[i]);
}
free(string_list);
What is weak about this:
It uses scanf() rather than fgets() and then parses, has minimal error checking, does not take in strings with spaces, does not handle over-long input, strdup() is not standard -yet, etc.
So the above is a baby step. Better code would handle the weak issues.
#include <stdio.h>
#include <string.h>
int main(void) {
const int NUM_VALS = 20;
int i;
int actualInput;
char userString[actualInput][NUM_VALS];
int matchCount = 0;
scanf("%d", &actualInput);
for (i = 0; i < actualInput; ++i) {
scanf("%s", userString[i]);
printf("%s", userString[i]);
}
return 0;
}
Output:
b'hellohi\x80\x07#\xd2\x05#\x9a\x16[\xea\xccp\xa6\x15\xf6\x18+\xbf\x87\x8a#\x14)\x05#\xfe\x7f'b'\x92\x1fk\xb3\xfe\x7f\xfe\x7f\x118\x08\xe8\x03\x0eY\x03k\xb3\xfe\x7f\xfe\x7f\xb2Y{\xe8C}8\r\x8b-u{\x8cx86_64'F-8sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin/usr/sbin:/usr/bin:/sbin:/binsbin:/binTF-88tf8RELOAD=/usr/lib/x86_64-linux-gnu/coreutils/libstdbuf.so64-linux-gnu/coreutils/libstdbuf.sols/libstdbuf.soout
I've tried some variations replacing userString[i] with userString in the scanf function. The result is outputting 50,000 inputs of my last string. I don't understand what's happening.
The problem is this sequence of code:
int actualInput;
char userString[actualInput][NUM_VALS];
int matchCount = 0;
scanf("%d", &actualInput);
The first line declares a variable called actualInput but doesn't assign a value to that variable.
The second line declares a variable length array (VLA) using the value in actualInput. Using the value of an uninitialized variable results in undefined behavior, which basically means that after that point in the code, anything can happen. What's likely happening (based on your description of the problem) is that actualInput is either zero, or a small number, so you get an array that's too small to hold your input.
The last line (with the scanf) finally assigns a value to actualInput. You may be thinking that the array will resize itself when actualInput is changed. That definitely does not happen. In C, after a VLA is created, its size cannot be changed.
The solution is simple, rearrange the code so that things are done in the proper order:
int actualInput;
scanf("%d", &actualInput);
char userString[actualInput][NUM_VALS];
int matchCount = 0;
As a side note, you should really do some error checking to make sure that the user inputs a reasonable number, before using that number to create an array. For example
int actualInput;
if (scanf("%d", &actualInput) != 1 || actualInput < 1 || actualInput > 1000)
{
printf("That is not a valid array size\n");
return 1;
}
char userString[actualInput][NUM_VALS];
you cant declare it as a 2D array then treat it as a normal array .
each case should include only one letter but it can't be done automatically , I suggest you add this :
for (i = 0; i < actualInput; ++i)
{
gets(stri);
for (k=0;k<strlen(stri);k++)
userString[i][j]=stri[j];
}
I'm having trouble with trying to manipulate 2d dynamic arrays in C. What I want to do is to store a char string in every row of the the 2d array then perform a check to see if the string contains a certain character, if so remove all occurrences then shift over the empty positions. What's actually happening is I get an exit status 1.
More about the problem, for example if I have
Enter string 1: testing
Enter string 2: apple
Enter string 3: banana
I would want the output to become
What letter? a // ask what character to search for and remove all occurences
testing
pple
bnn
Here is my full code:
#include <stdio.h>
#include <stdlib.h>
void removeOccurences2(char** letters, int strs, int size, char letter){
// Get size of array
// Shift amount says how many of the letter that we have removed so far.
int shiftAmt = 0;
// Shift array says how much we should shift each element at the end
int shiftArray[strs][size];
// The first loop to remove letters and put things the shift amount in the array
int i,j;
for(i=0;i < strs; i++){
for(j = 0; j < size - 1; j++) {
if (letters[i][j] == '\0'){
break;
}
else {
// If the letter matches
if(letter == letters[i][j]){
// Set to null terminator
letters[i][j] = '\0';
// Increase Shift amount
shiftAmt++;
// Set shift amount for this position to be 0
shiftArray[i][j] = 0;
}else{
// Set the shift amount for this letter to be equal to the current shift amount
shiftArray[i][j] = shiftAmt;
}
}
}
}
// Loop back through and shift each index the required amount
for(i = 0; i < strs; i++){
for(j = 0; j < size - 1; j++) {
// If the shift amount for this index is 0 don't do anything
if(shiftArray[i][j] == 0) continue;
// Otherwise swap
letters[i][j - shiftArray[i][j]] = letters[i][j];
letters[i][j] = '\0';
}
//now print the new string
printf("%s", letters[i]);
}
return;
}
int main() {
int strs;
char** array2;
int size;
int cnt;
int c;
char letter;
printf("How many strings do you want to enter?\n");
scanf("%d", &strs);
printf("What is the max size of the strings?\n");
scanf("%d", &size);
array2 = malloc(sizeof(char*)*strs);
cnt = 0;
while (cnt < strs) {
c = 0;
printf("Enter string %d:\n", cnt + 1);
array2[cnt] = malloc(sizeof(char)*size);
scanf("%s", array2[cnt]);
cnt += 1;
}
printf("What letter?\n");
scanf(" %c", &letter);
removeOccurences2(array2,strs,size,letter);
}
Thanks in advance!
You can remove letters from a string in place, because you can only shorten the string.
The code could simply be:
void removeOccurences2(char** letters, int strs, int size, char letter){
int i,j,k;
// loop over the array of strings
for(i=0;i < strs; i++){
// loop per string
for(j = 0, k=0; j < size; j++) {
// stop on the first null character
if (letters[i][j] == '\0'){
letters[i][k] = 0;
break;
}
// If the letter does not match, keep the letter
if(letter != letters[i][j]){
letters[i][k++] = letters[i][j];
}
}
//now print the new string
printf("%s\n", letters[i]);
}
return;
}
But you should free all the allocated arrays before returning to environment, and explicitely return 0 at the end of main.
Well, there are several issues on your program, basically you are getting segmentation fault error because you are accessing invalid memory which isn't allocated by your program. Here are some issues I found:
shiftAmt isn't reset after processing/checking each string which lead to incorrect value of shiftArray.
Values of shiftArray only set as expected for length of string but after that (values from from length of each string to size) are random numbers.
The logic to delete occurrence character is incorrect - you need to shift the whole string after the occurrence character to the left not just manipulating a single character like what you are doing.
1 & 2 cause the segmentation fault error (crash the program) because it causes this line letters[i][j - shiftArray[i][j]] = letters[i][j]; access to unexpected memory. You can take a look at my edited version of your removeOccurences2 method for reference:
int removeOccurences2(char* string, char letter) {
if(!string) return -1;
int i = 0;
while (*(string+i) != '\0') {
if (*(string+i) == letter) {
memmove(string + i, string + i + 1, strlen(string + i + 1));
string[strlen(string) - 1] = '\0'; // delete last character
}
i++;
}
return 0;
}
It's just an example and there is still some flaw in its logics waiting for you to complete. Hint: try the case: "bananaaaa123"
Happy coding!
"...if the string contains a certain character, if so remove all occurrences then shift over the empty positions."
The original string can be edited in place by incrementing two pointers initially containing the same content. The following illustrates.:
void remove_all_chars(char* str, char c)
{
char *pr = str://pointer read
char *pw = str;//pointer write
while(*pr)
{
*pw = *pr++;
pw += (*pw != c);//increment pw only if current position == c
}
*pw = '\0';//terminate to mark last position of modified string
}
This is the cleanest, simplest form I have seen for doing this task. Credit goes to this answer.
Program to calculate the average of n numbers given by the user.
Okay so I have this program whose purpose is what you have read above. Its output is not quite right. I figured out what the problem is but couldn't find the solution as I am not a leet at programming (newbie actually). Here is the code:
#include <stdio.h>
int main(void) {
char user_data[100];
long int sum = 0;
double average;
unsigned int numbers_count = 0;
for (int i = 0; i <= 99; ++i)
user_data[i] = 0;
unsigned int numbers[100];
for (int i = 0; i <= 99; ++i)
numbers[i] = 0;
printf("Please enter the numbers:");
fgets(user_data, sizeof(user_data), stdin);
int i = 0;
while (user_data[i] != 0) {
sscanf(user_data, "%u", &numbers[i]);
++i;
}
i = 0;
while (numbers[i] != 0) {
sum += numbers[i];
++i;
}
i = 0;
while (numbers[i] != 0) {
++numbers_count;
++i;
}
average = (float)sum / (float)numbers_count;
printf("\n\nAverage of the entered numbers is: %f",average);
return 0;
}
Now here comes the problem.
When I enter an integer say 23, it gets stored into the user_data in two separate bytes. I added a loop to print the values of user_data[i] to figure out what was wrong.
i = 0;
while (i <= 99) {
printf("%c\n",user_data[i]);
++i;
}`
and the result was this
user_data insight
This was the first problem, here comes the second one.
I added another loop same like the above one to print the numbers stored in numbers[100] and figure out what was wrong and here is the output. Here's a sample
numbers stored in numbers[]
Now my main question is
How to extract the full number from user_data?
I believe it could be helpful to layout user_data after the fgets() of "23" (assuming Linux or Mac new line):
+-----+-----+----+----+
| '2' | '3' | \n | \0 | .....
+-----+-----+----+----+
0 1 2 3
Note that user_data[0] does not contain 2 (the number 2)! It contains '2' (the character '2') whose code is (again, assuming Linux) 0x32 (in hex or 50 in decimal).
This is why your attempt to print the values of user_data[] have not been fruitful: you were trying to print the representation of the number, not the number itself.
To convert that string to the integer it represents, you can do something like:
num = atoi(user_data)
The function atoi() does the work for you. A more flexible function is strtol() which does the same but for long int (and also can handle string that represents numbers in a base that is not 10).
I hope this answers to your question: How to extract the full number from user_data?
There are some other points where you should clean up and simplify your code, but you can open another question in case you need help.
Try this:
#include<stdio.h>
#include<stdlib.h>
int main(void)
{
int i;
char user_data[100];
long int sum = 0;
double average;
unsigned int numbers_count = 0;
for( i=0; i<= 99; ++i)
user_data[i] = 0;
unsigned int numbers[100];
for( i=0; i<= 99; ++i)
numbers[i] = 0;
printf("Please enter the numbers:");
fgets(user_data,sizeof(user_data),stdin);
//int p=0;//use with strtol(see further code)
i = 0;
int j;//this will store each number in numbers array.. so this is also the count of numbers stored - 1
for(j=0;;){
for(i=0;i<strlen(user_data);i++)
{
if(user_data[i]=='\n'){
break;
}
if(user_data[i]==' '){
j++;
i++;
//p=i;//to be used with strtol
}
numbers[j]=(numbers[j]*10)+((user_data[i]-48));//alternatively use => numbers[j]=strtol(user_data+p,NULL,10);
}
break;
}
i = 0;
while( i<=j)
{
sum += numbers[i];
++i;
}
average = (float)sum/(j+1);
printf("\n\nAverage of the entered numbers is: %f",average);
return 0;
}
Sample input
10 11 12
Sample output
11.00000000
I have shown two approaches to solve this:
One is straight-forward, subtract 48 from each char and add it to numbers array(ASCII manipulation) .
Other is to use strtol. Now strtol converts the number pointed by the char pointer(char array in this case) until the next char is not a number. So use pointer arithmetic to point to further numbers(like here I have added p(yeah I know p is not a good variable name, so does i and j!)).
There are more ways to solve like using atoi library functions.
regarding the posted code:
what happens if one of the numbers is zero?
What happens if the sum of the numbers exceeds the capacity of 'sum'
#include <stdio.h> // sscanf(), fgets(), printf()
#include <stdlib.h> // strtol()
#include <string.h> // strtok()
// eliminate the 'magic' number by giving it a meaningful name
#define MAX_INPUTS 100
int main(void)
{
// the array can be initialized upon declaration
// which eliminates the 'for()' loop to initialize it
// char user_data[100];
// and
// initialization not actually needed as
// the call to 'fgets()' will overlay the array
// and 'fgets()' always appends a NUL byte '\0'
char user_data[ MAX_INPUTS ];
long int sum = 0;
double average;
// following variable not needed
// unsigned int numbers_count = 0;
// following code block not needed when
// 'user_data[]' initialized at declaration
// for (int i = 0; i <= 99; ++i)
// user_data[i] = 0;
// not needed, see other comments
//unsigned int numbers[100];
// not needed, as 'numbers' is eliminated
// for (int i = 0; i <= 99; ++i)
// numbers[i] = 0;
printf("Please enter the numbers:");
// should be checking the returned value
// to assure it is not NULL
// And
// this call to 'fgets()' is expecting
// all the numbers to be on a single input line
// so that could be a problem
fgets(user_data, sizeof(user_data), stdin);
// the following two code blocks will not extract the numbers
// for a number of reasons including that 'sscanf()'
// does not advance through the 'user_data[]' array
// int i = 0;
// while (user_data[i] != 0) {
// sscanf(user_data, "%u", &numbers[i]);
// ++i;
// }
// i = 0;
// while (numbers[i] != 0) {
// sum += numbers[i];
// ++i;
// }
// suggest the following,
// which also eliminates the need for 'numbers[]'
// note: the literal " \n" has both a space and a newline
// because the user is expected to enter numbers,
// separated by a space and
// 'fgets()' also inputs the newline
int i = 0;
char *token = strtok( user_data, " \n");
while( token )
{
// not everyone likes 'atoi()'
// mostly because there is no indication of any error event
// suggest using: 'strtol()'
//sum += atoi( token );
sum += strtol( token, NULL, 10 ) // could add error checking
i++;
token = strtok( NULL, " \n" );
}
// the value assigned to 'numbers_count'
// is already available in 'i'
// suggest eliminate the following code block
// and
// eliminate the 'numbers_count' variable
// i = 0;
// while (numbers[i] != 0) {
// ++numbers_count;
// ++i;
// }
// 'average' is declared as a 'double',
// so the casting should be to 'double'
// and
// if incorporating the prior comment about 'numbers_count'
// average = (float)sum / (float)numbers_count;
average = (double)sum / (double)i'
// to have the text immediately displayed on the terminal
// place a '\n' at the end of the format string.
// without adding the '\n' the text only displays
// as the program exits
// printf("\n\nAverage of the entered numbers is: %f",average);
printf("\n\nAverage of the entered numbers is: %f\n",average);
return 0;
} // end function: main