Explanation with arrays and strings - c

I have found a code that shows the frequency of a character in a string. Specifically,
#include <stdio.h>
int main(){
char string[100];
int i, frequency[256] = {0};
printf("Enter a String\n");
gets(string);
for(i=0; string[i]!=0; i++){
frequency[string[i]]=frequency[string[i]]+1;
}
printf("\nCharacter Frequency\n");
for(i=0; i < 256; i++){
if(frequency[i] != 0){
printf("%5c%10d\n", i, frequency[i]);
}
}
return 0;
}
However, I do not understand this:
frequency[string[i]]=frequency[string[i]]+1;
What does it do? How does it behave? I believe that string[i] is the length of frequency? But I am not sure.

Here, the value of string[i] serves as the index for the array frequency.
By saying
frequency[string[i]]=frequency[string[i]]+1;
you're trying to increment the value of the frequency[string[i]] element by 1.
This can also be re-written as
frequency[string[i]]++;
Having said that,
Never use gets(), it seriously suffers from buffer overflow issues. Use fgets() instead.
int main() should be int main(void) at least to conform to the standard.
It is a good practice to always initialize your local variables, like char string[100] = {0};
Link to the ASCII table, for your reference.

char values can be used as array index. string[i] is a char and it is being used as array index in the statement
frequency[string[i]]=frequency[string[i]]+1;
So, if string[i] = 'c' and it's occurrence in the string for ith iteration is 1, then the above expression will increment frequency of character 'c', i.e. frequency[string[i]] by 1.
In this case frequency[string[i]] is equivalent to frequency['c'] which in turn equivalent to frequency[99], where 99 is ASCII equivalent of character 'c'.

Related

Add up digit from char array in c language

I am new to C programming and trying to make a program to add up the digits from the input like this:
input = 12345 <= 5 digit
output = 15 <= add up digit
I try to convert the char index to int but it dosent seems to work! Can anyone help?
Here's my code:
#include <stdio.h>
#include <string.h>
int main(){
char nilai[5];
int j,length,nilai_asli=0,i;
printf("nilai: ");
scanf("%s",&nilai);
length = strlen(nilai);
for(i=0; i<length; i++){
int nilai1 = nilai[i];
printf("%d",nilai1);
}
}
Output:
nilai: 12345
4950515253
You have two problems with the code you show.
First lets talk about the problem you ask about... You display the encoded character value. All characters in C are encoded in one way or another. The most common encoding scheme is called ASCII where the digits are encoded with '0' starting at 48 up to '9' at 57.
Using this knowledge it should be quite easy to figure out a way to convert a digit character to the integer value of the digit: Subtract the character '0'. As in
int nilai1 = nilai[i] - '0'; // "Convert" digit character to its integer value
Now for the second problem: Strings in C are really called null-terminated byte strings. That null-terminated bit is quite important, and all strings functions (like strlen) will look for that to know when the string ends.
When you input five character for the scanf call, the scanf function will write the null-terminator on the sixth position in the five-element array. That is out of bounds and leads to undefined behavior.
You can solve this by either making the array longer, or by telling scanf not to write more characters into the array than it can actually fit:
scanf("%4s", nilai); // Read at most four characters
// which will fit with the terminator in a five-element array
First of all, your buffer isn't big enough. String input is null-terminated, so if you want to read in your output 12345 of 5 numbers, you need a buffer of at least 6 chars:
char nilai[6];
And if your input is bigger than 5 chars, then your buffer has to be bigger, too.
But the problem with adding up the digits is that you're not actually adding up anything. You're just assigning to int nilai1 over and over and discarding the result. Instead, put int nilai1 before the loop and increase it in the loop. Also, to convert from a char to the int it represents, subtract '0'. All in all this part should look like this:
int nilai1 = 0;
for (i = 0; i < length; i++) {
nilai1 += nilai[i] - '0';
}
printf("%d\n", nilai1);
For starters according to the C Standard the function main without parameters shall be declared like
int main( void )
This character array
char nilai[5];
can not contain a string with 5 digits. Declare the array with at least one more character to store the terminating zero of a string.
char nilai[6];
In the call of scanf
scanf("%s",&nilai);
remove the operator & before the name nilai. And such a call is unsafe. You could use for example the standard function fgets.
This call
length = strlen(nilai);
is redundant and moreover the variable length should be declared having the type size_t.
This loop
for(i=0; i<length; i++){
int nilai1 = nilai[i];
printf("%d",nilai1);
}
entirely does not make sense.
The program can look the following way
#include <stdio.h>
#include <ctype.h>
int main(void)
{
enum { N = 6 };
char nilai[N];
printf( "nilai: ");
fgets( nilai, sizeof( nilai ), stdin );
int nilai1 = 0;
for ( const char *p = nilai; *p != '\0'; ++p )
{
if ( isdigit( ( unsigned char ) *p ) ) nilai1 += *p - '0';
}
printf( "%d\n", nilai1 );
return 0;
}
Its output might look like
nilai: 12345
15

concatenating (adding) two charcter strings

I was told to write a program containing a concatenate function. This program should collect the input strings using fgets (&s1[0], len1+1, stdin)
and then add the two to each other to produce a final product.
My problem falls in that the program compiles but it doesn't display anything on the screen whatsoever, here's what I've got. I couldn't see how I could get it solved without this method of approach.
//function to terminate the program incase reach of 0
int str_len (char s[])
{
int i=0;
while (s[i]= NULL)
++i;
return i+1;
}
char string_cat (char*s1, char*s2)
{
//ADDING THE TWO STRINGS
int str_len(char s[])
char *s1 [80]= {'\0'};
char *s2 [40]= {'\0'};
int len1=str_len(s1);
int len2=str_len(s2);
if (int x=0; len1+len2<80; \0;
return;
}
int main ()
{
char string_cat(char*s1,char*s2)
int str_len(char s[])
//RECIVING THE STRINGS TO ADD
char s1 [80];
char s2 [40];
int i=0;
for (i; i !=0; ++i)
{
printf("What is the first sentence?: ")
fgets(*s1[0], 75+1, stdin);
printf("What is the second sentence?:")
fgets(*s2[0],35+1,stdin);
string_cat(*s1,*s2);
printf("The two sentences added together produce the following: %c",s1 )
}
++i
return 0;
}
aside from the mistake with the for loop that others have pointed out, the while loop in your str_len function is wrong.
you should've used while(s[i] != NULL) instead of s[i] = null. one equal sign, "=", is assignment; two equal signs, "==", is comparisons; and exclamation equals, "!=", means not equal.
Secondly, you reassign your s1 and s2 to different memory locations in your string_cat function with their first character as NULL, "\0". this will always give your str_len a length of 0 if corrected your str_len function as pointed out above, and a length of random number if not corrected based on what's occupying your memory at run time.
thirdly [still in the string_cat function], your if(int x = 0; len1 + len2 < 80; \0; doesn't make sense. you're not doing any concatenations in this function at all.
Sorry for not providing you with the solution as this is a simple exercise. I feel like spoiling you if I were to provide you with the code.
First problem is here
int i=0;
for (i; i !=0; ++i)
You set value 0 to the variable i, and then you check if it does not equal 0. This check does not obviosly pass because i equals 0.
The second problem is also the loop. I can't really get the reason you need the loop it at all, because i is not used at all, exept the increment. So as far as i get it, the loop is not needed at all.
In your code having lot of compilation error. Copy paste the code what you have compiled.
Check this line of code
int i=0;
for (i; i !=0; ++i)
Because of this you are not getting any thing. In for loop you have condition i !=0 which always fail so it's not entering inside the loop.

Pointer De-referencing

#include<stdlib.h>
#include<stdio.h>
#define NO_OF_CHARS 256
/* Returns an array of size 256 containg count
of characters in the passed char array */
int *getCharCountArray(char *str)
{
int *count = (int *)calloc(sizeof(int), NO_OF_CHARS);
int i;
for (i = 0; *(str+i); i++)
count[*(str+i)]++;
return count;
}
/* The function returns index of first non-repeating
character in a string. If all characters are repeating
then returns -1 */
int firstNonRepeating(char *str)
{
int *count = getCharCountArray(str);
int index = -1, i;
for (i = 0; *(str+i); i++)
{
if (count[*(str+i)] == 1)
{
index = i;
break;
}
}
free(count); // To avoid memory leak
return index;
}
/* Driver program to test above function */
int main()
{
char str[] = "geeksforgeeks";
int index = firstNonRepeating(str);
if (index == -1)
printf("Either all characters are repeating or string is empty");
else
printf("First non-repeating character is %c", str[index]);
getchar();
return 0;
}
I really can't grasp the following lines:
count[*(str+i)]++;
amd
int *getCharCountArray(char *str)
{
int *count = (int *)calloc(sizeof(int), NO_OF_CHARS);
int i;
for (i = 0; *(str+i); i++)
count[*(str+i)]++;
return count;
}
The program is used to find the first Non-Repeating character in the string.
*(str+i) is same as str[i]. The line:
for (i = 0; *(str+i); i++)
is the same as:
for (i = 0; str[i]; i++)
The statements in the loop will be executed as long as str[i] evaluates to non-zero. Since C strings are arrays of characters that are terminated by a null character, the for loop will be executed for each character in str. It will stop when the end of the string is reached.
count[*(str+i)]++;
is the same as:
count[str[i]]++;
If str[i] is 'a', this line will increment the value of count['a'], which is count[97] in ASCII encoding.
At the end of the loop, count will be filled with integers that represent the number of times a particular character appears in str.
I really can't grasp the following lines:
count[*(str+i)]++;
Work from the outside in:
since str is a pointer to char and i is an int, str + i is a pointer to the char that is i chars after the one str itself points to
*(str+i) dereferences pointer str+i, meaning it evaluates to the char the pointer points to. This is exactly equivalent to str[i].
count[*(str+i)] uses the char at index i in string str as an index into dynamic array count. The expression designates the int at that index (since count points to an array of ints). See also below.
count[*(str+i)]++ evaluates to the int at index *(str+i) in the array count points to. As a side effect, it increments that array element by one after the value of the is determined expression. This overall expression is present in your code exclusively for its side effect.
It is important to note that although space is reserved in array count for counting appearances of 256 distinct char values, the expression you asked about is not a safe way to count all of them. That's because type char can be implemented as a signed type (at the C implementer's discretion), and it is common for it to be implemented that way. In that case, only the non-negative char values correspond to array elements, and undefined behavior will result if the input string contains others. Safer would be:
#include <stdint.h>
# ...
count[(uint8_t) *(str+i)]++;
i.e. the same as the original, except for explicitly casting each character of the input string to an unsigned 8-bit value.
Overall, the function simply creates an array of 256 ints, one for each possible char value, and scans the string to count the number of occurrences of each char value that appears in it. It then returns this array of occurrence counts.
This code is equivalent to the confusing loop you posted. Does it help?
*(str + i) is confusing way of expressing str[i] and IMO inappropriate here.
for (i = 0; str[i] != '\0'; ++i)
{
char curr_char = str[i];
++count[curr_char];
}
In for loop there are three things we need to consider :
Explanation of for loop
Initialization of counter variable( i in your eg.). 2) Condition (*(str+i)) 3) Increment/decrement part (i++).
the for loop gets executed till the condition is true(i.e any non zero value) . so *(str+i) is providing a non zero value until there is any character in the array..
count[*(str+i)]++; // it is counting the number of characters in the array by incrementing the string character by character.
count[*(str+i)]++ =>count[*(str+i)]=count[*(str+i)]+1
Now consider one scenario:
char str[] = "aaab";
*(str+i)/str[i] Will show char like 'a','b'...etc.
So
count[*(str+i)]++=count['a']++ Mean;
count['a']=count['a']+1 // Will store iteration of a=1
count['a']=count['a']+1 // Will Update iteration of a=2
count['a']=count['a']+1 // Will Update iteration of a=3
and like other character.
So count[*(str+i)]++ will update occrance of charcarter in updated count.

Is it possible to get the number of elements currently stored in an array in C?

I know it's possible to use the sizeof function to get the size, but it doesn't get a true count of the array length. If I set an array of int 50 and I stored only 10 numbers in there, I would want to get 10 as the number of elements, but of course that won't happen. I know this is definitely a trivial question, but bear with me here and help me on this if it is possible.
My code so far takes an entire sentence and stores it in an array.
#include <stdio.h>
#include <string.h>
int main()
{
int i=0;
char array[50]={0};
fgets(array, 50, stdin);
int len = sizeof(array); // it doesn't work :((((((
for(i=0; i<len; i++)
{
printf("%c\n", array[i]);
}
return 0;
}
As you guys can see, if the user decides to only enter a word of lets say "Bobby Foo" then I would want len number of 9 including the space, but the sizeof function only gets length of the size of the array declared which is 50.. >.>..
Q: Is it possible to get the number of elements currently stored in an array in C?
Short answer: No. You need to track this information yourself.
You happen to be using fgets() with a character array. Since in this case you're getting a C "string", you can use the C function strlen().
It's worth noting that fgets() will also return a newline - so your string might be a one (Mac, Linux) or two (DOS/Windows) characters longer than you expect.
PS:
Here is a bit more about C strings, including the concept of "null termination" (if you're not already familiar with them):
http://www.cprogramming.com/tutorial/c/lesson9.html
Use strlen to get the size of the array. You need to include string.h.
sizeof() is not a function it is an operator. When sizeof is applied to the name of a static array (not allocated through malloc), the result is the size in bytes of the whole array.
If you are using fgets, then you need to remove \n from the string. A simple way would be:
array[strlen(array) - 1] = '\0';
A quick example:
#include <stdio.h>
#include <string.h>
#include <stddef.h>
int main()
{
int i=0;
char array[50]={0};
char *p;
fgets(array, 50, stdin);
//Remove `\n` from the array.
if ((p=strchr(array, '\n')) != NULL)
*p = '\0';
size_t len = strlen(array); // Use strlen to find the length of string
for(i=0; i<len; i++)
{
printf("%c\n", array[i]);
}
return 0;
}

Cannot figure this out C programming

The program is supposed to remove everything but the letters and create a new string which will have only the letters in upper-case.
However, it is not printing the results.
Here's the code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char *remove_up(char input[])
{
char *new_str = (char *) malloc(strlen(input) + 1);
int i=0;
int j=0;
while (i < strlen(input))
{
if (((input[i]) >= 65 && (input[i]<=90)) || ((input[i]>=97) && (input[i]<=122)))
{
new_str[j]= toupper(input[i]);
i++;
j++;
}
else i++;
}
return new_str;
}
int main()
{
char str_1[100];
char str_2[100];
printf("Enter first word: ");
fgets(str_1, sizeof(str_1), stdin);
printf("Enter second word: ");
fgets(str_2, sizeof(str_2), stdin);
char *up_str_1 =(char *) malloc(strlen(str_1) + 1);
char *up_str_2 =(char *) malloc(strlen(str_2) + 1);
up_str_1= remove_up(str_1);
up_str_2= remove_up(str_2);
printf("%s", up_str_1);
printf("\n");
printf("%s", up_str_2);
return 0;
}
There are a few problems, but because this is tagged homework, I'll point them out but not give you the answer.
First of all, this doesn't do what you think:
int i, j = 0;
j will be initialized, but i probably won't start at 0. You need to initialize i to 0 as well.
Next, there's a typo - you missed a closing ] at (input[i<=122).
Finally, based on your answers to the questions, you probably aren't printing the result anyway: look up printf() or cout or whatever you prefer to use for outputting values.
It doesn't print results because you haven't used any print statements to show what comes back from your calls to remove_up.
To understand what is going on in your remove_up function, you need to understand this:
http://www.asciitable.com/
This code:
if (((input[i]) >= 65 && (input[i]<=90)) || ((input[i]>=97) && (input[i<=122)))
Is checking to see if a character is an alphabetic character in the ascii character set between these two ranges. Look at the link above. If it is in this set it's converting it to upper (redundant for half the data) and saving the result in your newly malloc'd string.
Problems:
1. You never set a null terminator in "new_str"
2. You never seem to free anything (though in this code it is trivial, in real code you could create problems, i.e. memory leaks).
3. "i" is redundant in the while loop. It's in both the if and else...
4. Rethink how you're using malloc (you probably don't want to use it this way in your custom functions unless you're going to cleanup after yourself)
There is probably more I'm missing, but that should help you see some problems.
Double check your use of parenths - you have more than needed. You are also missing a ']' in that if statement. Surprised it compiles.
change int i, j = 0; to int i = 0, j = 0;. Your i was initialized with a garbage value greater than strlen(input), and hence never entered the while loop.

Resources