getting the length of initiated values in a character array - c

So lets say I have a character array called str of size 12, and I input 1000110 in the array, with str[0] = 1, str[1] = 0 etc... I tested the array by printing it in a for loop, it works.
I then want to count how many integers are initiated in the array. In this case, the value should be: 7
Here is my code, for whatever reason, the output is 1, not 7.
int length;
length = 12;
int actual_length()
{
int act_length = 0;
int i;
for (i = 0; i < length; i++)
{
if ( str[i] == 0 || str[i] == 1 )
{
act_length++;
}
}
printf("TEST ACTUAL LENGTH: %d\n", act_length);
return act_length;
}
I also tried
(int)str[i]
for the comparisons, but that did not change the outcome.

You have a string that consists of characters.
You need to compare against the character value:
if ( str[i] == '0' || str[i] == '1' )

Related

Converting value from a string into an int

I have read this question ( Convert a string into an int ) before posting but I still have doubts.
I am very new to C and I'am trying to write a function which takes a string as parameter , something like this :
"99Hello" or "123ab4c"
And then returns the first the numbers it found into an int. So the result would be :
99 or 123
I'am trying to do this by finding the characters in the string(which correspond to numbers in the ASCII table) and then store them in the int I have created and returned by the function.
I'am having trouble though because when I find those character ( which correspond to numbers) I don't know how to save them to an int data type variable or how to convert them. I know there is a function called atoi which does this automatically but I would like to know how to do this by myself.
This is what I wrote so far :
int ReturnInt(char *str)
{
int i;
int new;
i = 0;
new = 0;
while (str[i] != '\0')
{
if( str[i] >= '0' && str[i] <= '9')
{
str[i] = new - '0';
}
i++;
}
return (new);
}
I think you should be able to form the desired integer from digits by multiplying them by 10 and adding them while iterating. Moreover, I think your loop's terminating condition should also include isDigit check
For example, for input 99Hello
i = 0, new = 0 -> new = 0 * 10 + 9 (9)
i = 1, new = 9 -> new = 9 * 10 + 9 (99)
i = 2, condition not satisfied as it's not a digit
int ReturnInt(char str[]) {
int i;
int new;
i = 0;
new = 0;
while (str[i] != '\0' && (str[i] >= '0' && str[i] <= '9'))
{
int currentDigit = str[i] - '0';
new = new * 10 + currentDigit;
i++;
}
return (new);
}
You just have to take a place holder , and that has to be multiplied by 10 for every iteration so that we get 10, 100, 1000 place holders and we can add that quantity to remaining numbers.
#include <stdio.h>
#include <ctype.h>
int str2num(char*strnum);
int main()
{
char *num1 = "122AB";
char *num2 = "2345AB9C";
char *num3 = "A23AB9C";
printf("num1 = %d\n", str2num(num1));
putchar('\n');
printf("num2 = %d\n", str2num(num2));
putchar('\n');
printf("num3 = %d\n", str2num(num3));
return 0;
}
int str2num(char*strnum)
{
int num = 0;
int ph = 10;// for getting tens,100s etc
while(strnum && *strnum && isdigit(*strnum))
{
num = num * ph + ( (*strnum) - '0');
strnum++;
}
return num;
}

Digit Frequency Program (HackerRank)

I'm trying to compare each character of the given string with numbers 0 to 9, and on successful comparison, increment the count variable. Finally, printing the value of count variable for each of the numbers.
But these method isn't working out. Can't figure out why.
int main() {
char *s;
s = malloc(1024 * sizeof(char));
scanf("%[^\n]", s);
int i,j,count=0;
for(i=0;i<=9;i++)
{
for(j=0;j<strlen(s);j++)
{
if(s[j]==i)
{
count++;
}
}
printf("%d ",count);
}
return 0;
}
Finally, printing the value of count variable for each of the numbers.
So you need an array to store counters for each digit. It is strange that zero is excluded from counted digits.
In this if statement
if(s[j]==i)
you have to write at least
if( s[j] - '0' == i )
And moreover this loop
for(i=0;i<=9;i++)
also tries to count zeroes though you wrote that to count only digits 1-9 inclusively.
Your approach is inefficient because you are traversing the same character array several times.
And there is no sense to allocate a character array dynamically.
The program can look the following way
#include <stdio.h>
int main(void)
{
enum { M = 9, N = 1024 };
char s[N];
s[0] = '\0';
size_t counter[M] = { 0 };
fgets( s, N, stdin );
for ( const char *p = s; *p; ++p )
{
if ( '0' < *p && *p <= '9' )
{
++counter[*p - '0' - 1];
}
}
for ( size_t i = 0; i < M; i++ )
{
printf( "%zu ", counter[i] );
}
putchar( '\n' );
return 0;
}
If to enter for example a string like
12345678987654321246897531
then the output will be
3 3 3 3 3 3 3 3 2
In fact the character array is redundant for this task. Moreover it restricts the length of the entered sequence of digits. You could write the program without using a character array. For example
#include <stdio.h>
int main(void)
{
enum { M = 9, N = 1024 };
size_t counter[M] = { 0 };
for ( int c; ( c = getchar() ) != EOF && c != '\n'; )
{
if ( '0' < c && c <= '9' )
{
++counter[c - '0' - 1];
}
}
for ( size_t i = 0; i < M; i++ )
{
printf( "%zu ", counter[i] );
}
putchar( '\n' );
return 0;
}
if(s[j]==i) <<<<<<<<<
{
count++;
}
You are comparing the ordinal value of the character to an integer in the range 0 to 9. Which is not what you want.
You can convert a digit to int with this method:
char c = '5';
int x = c - '0';
So in your case it would be:
if(s[j] -'0' ==i)
{
count++;
}
In C a character value is a number, but it is not the number you are expecting here. When we have the character '2' and we check what it is equal to as a number we are really asking what the ASCII code of '2' is which in this case would be 50. You need to adjust your code so it converts the ASCII code into a numeric representation so 50 becomes 2. It is quite simple simply change your code so it looks like this
if((s[j] - '0') == i){
This works because the ASCII code of 0 is 48, the ASCII code of 1 is 49, etc etc.
TL;DR In C a character value is not equal to it's numeric value. You need to convert '5' to 5. To do this you adjust your code so you subtract the '0' character from your numeric character.

converting binary to multiple characters

I basically posted this question yesterday, but I'm running into a different type of error. So I'm trying to create a program where the user enters a 12-bit binary hamming code sequence like "100010010001" and it should print out its corresponding ASCII character, which in this case is 'A'.
The problem is it seems to work for single characters like 'A' but if I type the binary sequence 100010010001010110010010010010000011 which represents 'ABC' it prints out random characters unrelated to what should be printed out. I don't understand what's causing this problem?
char charToBin(char usersInput[]) {
char j = 0 ;
for (int i = 0; i <= 12 ; i++) {
if((i == 0) || (i == 1) || (i == 3) || (i == 7)){
continue ;
} ;
usersInput[j] = usersInput[i] ;
j++ ;
} ;
char c = strtol(usersInput, (char **)NULL, 2);
return c;
}
You should try my answer to that question of your yesterday. That solution will work and the first method should be really fast if you trying to break up the array into steps because it is a small array.
Nonetheless, for this code, the main problem that you have with your code is that you are trying to remove 4 indexes from a char array of 12 indexes without doing anything to tell strtol() that. So in your code, you only have to tell strtol() to stop at index 8 by injecting char '\0' at position 8 or the array which would be the 9th char. Also, since you are going to skip index 0 and 1, there is no point starting from index 0 and evaluating whether if it is index 0 or 1. You can start at index 2. Besides that, "i" should be less than 12 in your loop. That is because the last index of a 12 indexes array would be 11, and not 12. Also, j does not need to be a char. That should be an int.
char charToBin(char usersInput[]) {
int j = 0 ;
for (int i = 2; i < 12 ; i++) {
if( (i == 3) || (i == 7) ){
continue ;
} ;
usersInput[j] = usersInput[i] ;
j++ ;
} ;
usersInput[8] = '\0';
char c = strtol(usersInput, (char **)NULL, 2);
return c;
}
You must provide more info about your program like fully functional main(), example input and outputs, how to call the functions and etc.
But before that i think Same code like this may works for you.
p = len of usersInput / 12
char * charToBin(char usersInput[], int p) {
char j = 0 ;
char *c;
for(int n=0;n<p;n++){
for (int i = 0; i <= 12 ; i++) {
if((i == 0) || (i == 1) || (i == 3) || (i == 7)){
continue ;
} ;
usersInput[j+n] = usersInput[i+n] ;
j++ ;
} ;
c[n] = strtol(usersInput, (char **)NULL, 2);
}
return c;
}
Your for() loop should only iterate for 12 times,hence the condition should be i<12 and create a local character array as I did(to_Char[]) of length 9(8+1 for Null at end) and read appropriate bits into it from usersInput[], usersInput[] shouldn't be provided as input to strtol() as its of 32bits in length but our characters are just 8bits in length.
char charToBin(char usersInput[]) {
char j = 0;
char to_Char[9];
for (int i = 0; i < 12; i++) {
if ((i == 0) || (i == 1) || (i == 3) || (i == 7)) {
continue;
};
to_Char[j] = usersInput[i];
j++;
};
to_Char[j] = '\0';
char c = strtol(to_Char, (char**)NULL, 2);
return c;
}

Can a random string be generated with the frequency of characters in it, fixed?

I am trying to generate random strings, with the number of occurence of each character,fixed. For example- G (a character in the string),cannot appear more than 4 times , S, no more than 2 times and so on. My code is able to generate the strings but not the problem with the frequency of characters.
Is there any way, to fix this thing ? Any help will really be appreciated.
My current code is as follows:
#include<stdio.h>
#include<stdlib.h>
//The basic function here is like (rand() % range)+ Lower_bound
int rand_int(int a,int b)
{
if (a > b)
return((rand() % (a-b+1)) + b);
else if (b > a)
return((rand() % (b-a+1)) + a);
else
return a;
}
int main()
{
FILE *fptr;
fptr=fopen("C:\\Users\\Desktop\\dataset.txt","w");
int a,b,r,i,j,k;
char res;
a = 65;
b = 90;
k = 0;
char str[] = "ITLDGGCSSHLPLRCSVDSGCPGLRAGSVSCLPHGSIREGMECSRRHGVGIMGDRRDGSRDS"; //working string
char str_all[] = "ITLDGGCSSHLPLRCSVDSGCPGLRAGSVSCLPHGSIREGMECSRRHGVGIMGDRRDGSRDS";
char subs[] = "ACDEGHILMPRSTV"; //
fprintf(fptr,"%s",str);
fprintf(fptr,"%s","\n");
// value of j represents the number of strings to be displayed
for(j=0 ; j<10000 ; j++)
{
// getting all the sequence strings
// for changing the string at all positions
for(i=0 ; i<62 ; i++)
{
r = rand_int(a,b);
res = (char)r;
str_all[i] = res;
}
// substituting all the not required characters with required ones
for(i=0 ; i<62 ; i++)
{
if(str_all[i] == 'B' || str_all[i] == 'F' || str_all[i] == 'J' || str_all[i] == 'K' || str_all[i] == 'N' || str_all[i] == 'O' || str_all[i] == 'Q' || str_all[i] == 'U' || str_all[i] == 'W' || str_all[i] == 'X' || str_all[i] == 'Y' || str_all[i] == 'Z')
{
str_all[i] = subs[k++];
}
if(k>13)
k=0;
}
//printf("\nModified String for all string positions \n%s",str_all);
fprintf(fptr,"%s",str_all);
fprintf(fptr,"%s","\n");
}
fclose(fptr);
return 0;
}
You can simply create a fixed (constant) string with the available characters, and then shuffle a copy of it each time you need a random string. For how to shuffle an array in C, see here: Shuffle array in C
You can use the Fisher Yates shuffle. Put all your allowed characters into an array. Let's say you are allowed only 4 G's and 2 S's and nothing else. Your array would start out like this:
char array[] = { 'G', 'G', 'G', 'G', 'S', 'S' };
Then you apply the Fisher Yates shuffle. The Fisher Yates shuffle picks a random element from the array and swaps it with the last element. It then picks a random element from all but the last element and swaps it with the last but one element. It then picks a random element from all but the last two elements and swaps it with the last but two element and so on until you would be selecting a "random" element from only the first element.
Something like this:
for (int i = 0 ; i < N_ELEMENTS - 1 ; i++)
{
int ceiling = N_ELEMENTS - i;
int choice = arc4random_uniform(ceiling);
char tmp = array[ceiling - 1];
array[ceiling - 1] = array[choice];
array[choice] = tmp;
}
Use the above at your own risk since it has undergone no testing or even compiling.
I use arc4random_uniform because simply taking the modulus of a random number to get a random number in a smaller range skews the result. arc4random_uniform does not suffer from that issue.

Finding the most frequent character in a file in C

I'm writing a function that finds the most common alphabetic character in a file. The function should ignore all characters other than alphabetic.
At the moment I have the following:
int most_common(const char *filename)
{
char frequency[26];
int ch = 0;
FILE *fileHandle;
if((fileHandle = fopen(filename, "r")) == NULL){
return -1;
}
for (ch = 0; ch < 26; ch++)
frequency[ch] = 0;
while(1){
ch = fgetc(fileHandle);
if (ch == EOF) break;
if ('a' <= ch && ch <= 'z')
frequency[ch - 'a']++;
else if ('A' <= ch && ch <= 'Z')
frequency[ch - 'A']++;
}
int max = 0;
for (int i = 1; i < 26; ++i)
if (frequency[i] > frequency[max])
max = i;
return max;
}
Now the function returns how many times the most frequent letter occurred, not the character itself. I'm a bit lost, as I'm not sure if that's the way this function should look like at all. Does it make sense and how possibly can I fix the problem?
I would really appreciate your help.
The variable frequency is indexed by the character code. So frequency[0] is 5, if there have been 5 'a's.
In your code you are assigning the count to max, not the character code, so you're returning the count not the actual character.
You need to store both the maximum frequency count and the character code that it referred to.
I would fix this with:
int maxCount = 0;
int maxChar = 0;
// i = A to Z
for (int i = 0; i <= 26; ++i)
{
// if freq of this char is greater than the previous max freq
if (frequency[i] > maxCount)
{
// store the value of the max freq
maxCount = frequency[i];
// store the char that had the max freq
maxChar = i;
}
}
// character codes are zero-based alphabet.
// Add ASCII value of 'A' to turn back into a char code.
return maxChar + 'A';
Note that I changed int i = 1 to int i = 0. Starting at 1 would mean starting at B, which is a subtle bug you might not notice. Also, the loop should terminate at <= 26, otherwise you'd miss out Z too.
Note the braces. Your braces style (no braces for single-statement blocks) comes very highly un-recommended.
Also, i++ is more common than ++i in cases like this. In this context it will make no difference, so would advise i++.

Resources