I am working on an algorithm for a project and I ran across some code that I think may be helpful. However, as I try to read the code, I am having some difficulty understanding a statement in the code. Here is the code.
int firstWord[MAX_WORD_SIZE] = {0}, c = 0;
while (word1[c] != '\0') //word1 is char[] sent as a parameter
{
firstWord[word1[c]-'a']++;
c++;
}
I understand (I hope correctly) that the first line is setting up an integer array of my max size, and initializing elements to zero along with making the initial counter value "c" zero.
I understand that the while loop is looping through all of the characters of the word1[] array until it hits the final char '\0'
I am confused on the line firstWord[word1[c]-'a']++;
word1[c] should give a char, so what does doing the -'a' do? Does this cast the char to an integer which would allow you to access an element of the firstWord[] array and increment using ++? If so, which element or integer is given by word1[c]-'a'
word1[c]-'a' means the difference between the character in cth position of word1 and the integer value of 'a'. Basically it calculates the number of occurences of letters in a word.
So if word1[c] is 'b', then value of word1[c]-'a' will be ('b' - 'a') = 1. So the number of occurences of 'b' in the word will be incremented by 1.
This is a program that counts the number of letters a to z from a word. The key point here is, 'a' - 'a' has a value of 0, and 'b' - 'a' has a value of 1, etc.
For instance, if word1[c] is the letter 'd', then 'd' - 'a' is 3, so it would increment firstWord[3]. When the word has been iterated character by character, firstWord[3] contains the number of letter 'd' in the word.
it seems this code is doing a letter count
1 so what does doing the -'a' do?
if word1[c] is 'a' then word1[c]-'a' is 0
2 . Does this cast the char to an integer which would allow you to access an element of the firstWord[] array and increment using ++?
yes, it is integer promotion
3 .If so, which element or integer is given by word1[c]-'a'
if word1[c] is 'a' then word1[c]-'a' is 0
Related
I have a working piece of C code that completely removes every second char from a character array, making the original array half the size (half+1 if the size was odd)
..but I cannot figure out how it works.
void del_str(char string[]) {
int i,j;
for(i=0, j=0; string[i]!=0; i++) {
if(i%2==0) {
string[j++]=string[i];
}
}
string[j]=0;
}
//
example input: 'abcdefgh'
output from that: 'aceg'
what I thought the output would be: 'aacceegg'
The line I don't understand is
string[j++]=string[i];
I can write code that omits every second char, so the output would be:
'a c e g '
but I can't wrap my head around this.
Alternatively, how would you write a program that completely deletes every n-th char and their space in the original array? (producing the same output as the above code)
This code uses two position indexes, i and j. Initially, both indexes are initialized to zero. Index i is used for reading; index j is used for writing.
Index i is incremented at each step of the loop, because the increment i++ is in the header of the loop. Index j, on the other hand, is incremented every other iteration, because j++ happens only when i is even. Index i is always as close or closer to the end of the string than index j, because it moves "faster".
Null terminator is placed at the final position of j at the end of the loop to indicate the new position of string's end.
Perhaps it would be easier to see with a small example. Consider the initial string of "abcdef". Its representation in memory at the beginning of the algorithm is as follows:
'a' 'b' 'c' 'd' 'e' 'f' '\0'
Here is how it would change after each step of the loop:
'a' 'b' 'c' 'd' 'e' 'f' '\0'
'a' 'c' 'c' 'd' 'e' 'f' '\0'
'a' 'c' 'e' 'd' 'e' 'f' '\0'
'a' 'c' 'e' '\0' 'e' 'f' '\0'
Since C strings ignore everything after '\0', the "tail" of 'e' 'f' '\0' is not considered part of the string.
You are forgetting the if(i%2==0) which is crucial. This line basically skips every second character. Then, the line you have identified can be split in 2 parts:
string[j]=string[i]; // Overwrite the character at position j
j++; // Now increase j
The variable i keeps track of the position of the string you have reached while reading it; j is used for writing. In the end, you write 0 at position j to terminate the string.
i and j are not the clearest variable names. Perhaps renamig j to something like output would help.
Note when j is updated, only when you're at an odd position. So i is walking through the whole list while j brings up the read copying something from i back to the jth position, overwriting what was there before. The last line, string[j]=0, terminates your string.
I was going through the book "The C Programming language" by Kernighan and Ritchie and I am stuck at a topic.
Topic number 1.6 talks about Arrays. In the book, they have included a program that counts the digits, white spaces and other characters. The program goes like this:
#include <stdio.h>
main(){
int c,i,nother,nwhite;
int ndigit[10];
nwhite=nother=0;
for(i=0;i<10;++i)
ndigit[i]=0;
while((c=getchar())!=EOF)
if (c>='0' && c<='9')
++ndigit[c-'0'];
else if (c==' '|| c=='\t'||c=='\n')
++nwhite;
else
++nother;
printf("digits:");
for(i=0; i<10;++i)
printf(" %d",ndigit[i]);
printf(", white space = %d, other = %d\n", nwhite, nother);
}
First, I don't understand the purpose of the first for loop that is :
for(i=0;i<10;++i)
ndigit[i]=0;
And secondly, I can't understand the logic behind this part of the while loop:
if (c>='0' && c<='9')
++ndigit[c-'0'];
I really need someone to explain me the logic behind the program so that I can move further with C programming.
Thanks for the help!
This loop
for(i=0;i<10;++i)
ndigit[i]=0;
is used to set all elements of array ndigit to 0. The array will count numbers of eneterd digits.
Instead of this loop you could initially initialize all elements of the array to 0 when it was declared.
int ndigit[10] = { 0 };
As for this statement
if (c>='0' && c<='9')
++ndigit[c-'0'];
then if the entered char is a digit c>='0' && c<='9' then expression c-'0' gives you the integer value of the digit. Characters that correspond to character constant '0' - '9' internally in the computer memory represented by their ASCII or some other coding scheme codes. For example cgaracter '0' in ASCII has internal code 48, character '1' - 49, character '2' - 50 and so on. For example in EBCDIC cgaracter '0' has another code 240, character '1' - 241 and so on.
The C Standard guarantees that all digits follow each other.
So if variable c keeps some digit then expression c - '0' gives number from 0 (if c keeps '0' ) to 9 (if c keeps character '9' ).
This value (from 0 to 9) is used as an index in array ndigit.
For example let assume that c keeps character '6' . Then c - '0' will equal to integer number 6. So ndigit[6] is increased
++ndigit[c-'0']
This element of the array with index 6 counts how many times character '6' was entered.
ndigit[i] holds the number of times digit i (0-9) was counted. E.g., ndigit[5] contains the number of times the digit 5 was counted. So the first loop just initializes all to 0, as nothing was seen thus far.
The if statement checks whether the current character c is a digit. If so, it determines which digit it is by subtracting '0' from it. This will give the desired index, for which the value contained is increased by one.
I came across some examples where an array is indexed based on values from a different array.
Example:
char s[] = "aloha";
int l= strlen(s);
int array_count[256];
memset(array_count,0,256*sizeof(int));
for(int i=0;i<l;i++)
{
array_count[s[i]]++;// What exactly happens in this statement ??
}
I understood it as it checking and setting the alphabets in s[] as 1's in the array array_count,which is the alphabet set. Is that right ?
The code is keeping a histogram of how many times a given character appears in the string. Every time a character appears in the string, the array element corresponding to the ASCII value of that character is incremented by one.
The elements in array_count [] are all set to 0 by your memset(). Then your loop iterates through s[]. So in the first iteration:
array_count [s[i]]++ // first evaluate [i]
array_count [s[0]]++ // i is zero
array_count ['a']++ // s[0] is 'a'
array_count [97]++ // promotion of 'a' from char to int; ASCII value of 'a' is 97
array_count [97] is zero because of the memset, so because of the ++ it gets incremented to 1.
Similar magic happens with the rest of the characters in subsequent iterations; when the loop terminates, array_count [97] will be 2 because of the two 'a's in "aloha"; array_count [0] will be 1 because of the NUL character at the end of "aloha"; and you can figure out what the rest of the array will be (mostly zeros).
Each char in s[] has an unsigned int value (usually it's ascii value) inclusively between 0 and 255. array_count[] is initialised to all zeros by the memset. Then, by iterating through s[] from start to end with i in the for loop, the value of each char is used to index into array_count[] and increment it's value with ++. So you get a count of the char values in s[].
256 is possible letter in string. see the ascii table.
http://www.asciitable.com/
for(int i=0;i<l;i++)
{
array_count[s[i]]++; // What exactly happens in this statement ??
for i=0
s[i] = 'a'
ascii value of 'a' is 97
so it will increment arry_count[97] value from 0 to 1
}
I've written a small program to highlight the problem I'm having in C. I expected that in the following code, the display for loop would print 0, but exit on null; however, the loop exits on 0. What on earth am I missing / don't I understand? Your help is much appreciated.
#include <stdio.h>
int main (void)
{
int i = 0;
int iArray[] = {1, 2, 0, 4, 5, '\0'};
int cArray[] = {1, 2, 0, 4, 5, '\0'};
for(i=0; iArray[i] != '\0'; i++)
{
printf("\nElement: %d", iArray[i]);
}
for(i=0; cArray[i] != '\0'; i++)
{
printf("\nElement: %d", iArray[i]);
}
return 0;
}
Thanks,
Dan
The character literal '\0' is actually the same as the integer literal 0. So it stops when it hits the zero in your arrays.
To be more precise, '\0' is the octal value of zero. All character (and of course string) escape sequences with a leading zero are octal values, and will be inserted by the compiler "as is".
For arrays there is another way of finding the end, namely to get the the number of items in the array, like in
for(i=0; i < sizeof(iArray) / sizeof(iArray[0]); i++)
However, the trick of using e.g. sizeof(iArray) / sizeof(iArray[0]) to get the number of items in the array only works on real array. As soon as you pass an array around (e.g. as an argument to a function) it decays to a pointer and the "trick" can no longer be used.
0 == '\0'
So the iArray[i] != '\0' is the same of iArray[i] != 0
And your arrays contain 0 at the third element so the for loop will print only the 2 first elements of each array.
You're missing quotes, you seem to want to create a string of digits. The digit '1' is not the same as the character with the value 1.
Also, your arrays are mysteriously int, when they should be char.
Try:
const char iArray[] = { '1', '2', '0', '4', '5', '\0'};
which of course can be simpler written as:
const char iArray[] = "12045";
Because 0 and '\0 are equivalent. Actually the first is a number and the second is a char, which is casted (transformed) to int when inserted in the array. Probably you wanted to create a string of characters, so create an array of type char, wrap each number in '0' quotes and replace %d with %c.
Note: '0' represent the character zero, which is different from literal 0 and equivalent '\0', as you can see on the ASCII table. Same happens for 1 vs. '1'
If you intended an array of integers, then you cannot use '\0' as a terminator for the reason stated in the first sentence (unless you are sure 0 will not appear inside the array), keep the length of the array somewhere and use it for iterating.
It is a very trivial question but I don't know why I am not getting the correct output. Here is what I am trying to do:
char sendBuffer[1000];
int count=0:
while(count<10)
{
sendBuffer[0]=count;
sendBuffer[1]='a';
sendBuffer[2]='b';
sendBuffer[3]='c';
sendBuffer[4]='\0';
printf(%s,sendBuffer);
count=count+1;
}
In the output, all buffer is printed correctly except the first index. I want 1,2,3 and so on to be printed at the start of the buffer but it does not work. Please Help
You need to convert that number into a character. A cheap way to do it is:
sendBuffer[0] = '0' + count;
is there anyway to display integers greater than 9
If you need that you'll want to shift to more elaborate schemes. For example, if you want to convert an integer 42 into the string "42" you can say:
#define ENOUGH ((CHAR_BIT * sizeof(int) - 1) / 3 + 2)
char str[ENOUGH];
snprint(str, sizeof str, "%d", 42);
Credit for ENOUGH goes to caf.
printf(%s,sendBuffer); should be printf("%s",sendBuffer);
Change
sendBuffer[0]=count;
to
sendBuffer[0]='0' + count;
i.e. convert the integer 0...9 to the characters '0' ... '9'
Also add a quote i.e. printf("%s",sendBuffer);
Quoted from the question:
In the output, all buffer is printed correctly except the first
index.i want 1,2,3 and so on to be printed at the start of the buffer
but it does not work. Please Help
I think her problem is that she does not get any output for the first line. That is because in the first iteration, count is 0, i.e. sendBuffer[0] is 0 which is the '\0' character. Hence the string is treated as empty.
You are trying to print the ascii characters corresponding to decimal values 0-9 which are non-printable characters. If you need to print decimal 0-9 then initialise count to 48 which is the ascii decimal code for '0' and change the condition in the while block to count < 58; 57 is the ascii deciaml code for '9'. See below:
char sendBuffer[1000];
int count=48:
while(count<58)
{
sendBuffer[0]=count;
sendBuffer[1]='a';
sendBuffer[2]='b';
sendBuffer[3]='c';
sendBuffer[4]='\0';
printf(%s,sendBuffer);
count=count+1;
}
To convert an integer value to a char representation, add the value of the character '0':
sendBuffer[0]=count + '0';
Notice that's the character '0', not the number 0. This is because of how ascii values work. The char with a literal value of 0 is \0, the null terminator. Digit '0' has a literal value of 48, '1' 49 and so on.
This works for the digits 0-9. You can't put a char representation of a number bigger than that in a single char, obviously.
char sendBuffer[1000];
// take fixed stuff outside the loop
sendBuffer[1]='a';
sendBuffer[2]='b';
sendBuffer[3]='c';
sendBuffer[4]='\0';
// it's best not to rely on order of ASCII values
for(char* numbers="0123456789"; *numbers!=0; numbers++){// use for loop for numbers
sendBuffer[0] = *numbers;
printf("%s",sendBuffer);
}