converting binary to multiple characters - c

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;
}

Related

Checking whether a string consists of two repetitions

I am writing a function that returns 1 if a string consists of two repetitions, 0 otherwise.
Example: If the string is "hellohello", the function will return 1 because the string consists of the same two words "hello" and "hello".
The first test I did was to use a nested for loop but after a bit of reasoning I thought that the idea is wrong and is not the right way to solve, here is the last function I wrote.
It is not correct, even if the string consists of two repetitions, it returns 0.
Also, I know this problem could be handled differently with a while loop following another algorithm, but I was wondering if it could be done with the for as well.
My idea would be to divide the string in half and check it character by character.
This is the last function I tried:
int doubleString(char *s){
int true=1;
char strNew[50];
for(int i=0;i<strlen(s)/2;i++){
strNew[i]=s[i];
}
for(int j=strlen(s)/2;j<strlen(s);j++){
if(!(strNew[j]==s[j])){
true=0;
}
}
return true;
}
The problem in your function is with the comparison in the second loop: you are using the j variable as an index for both the second half of the given string and for the index in the copied first half of that string. However, for that copied string, you need the indexes to start from zero – so you need to subtract the s_length/2 value from j when accessing its individual characters.
Also, it is better to use the size_t type when looping through strings and comparing to the results of functions like strlen (which return that type). You can also improve your code by saving the strlen(s)/2 value, so it isn't computed on each loop. You can also dispense with your local true variable, returning 0 as soon as you find a mismatch, or 1 if the second loop completes without finding such a mismatch:
int doubleString(char* s)
{
char strNew[50] = { 0, };
size_t full_len = strlen(s);
size_t half_len = full_len / 2;
for (size_t i = 0; i < half_len; i++) {
strNew[i] = s[i];
}
for (size_t j = half_len; j < full_len; j++) {
if (strNew[j - half_len] != s[j]) { // x != y is clearer than !(x == y)
return 0;
}
}
return 1;
}
In fact, once you have appreciated why you need to subtract that "half length" from the j index of strNew, you can remove the need for that temporary copy completely and just use the modified j as an index into the original string:
int doubleString(char* s)
{
size_t full_len = strlen(s);
size_t half_len = full_len / 2;
for (size_t j = half_len; j < full_len; j++) {
if (s[j - half_len] != s[j]) { // x != y is clearer than !(x == y)
return 0;
}
}
return 1;
}
This loop
for(int j=strlen(s)/2;j<strlen(s);j++){
if(!(strNew[j]==s[j])){
true=0;
}
}
is incorrect. The index in the array strNew shall start from 0 instead of the value of the expression strlen( s ) / 2.
But in any case your approach is incorrect because at least you are using an intermediate array with the magic number 50. The user can pass to the function a string of any length.
char strNew[50];
The function can look much simpler.
For example
int doubleString( const char *s )
{
int double_string = 0;
size_t n = 0;
if ( ( double_string = *s != '\0' && ( n = strlen( s ) ) % 2 == 0 ) )
{
double_string = memcmp( s, s + n / 2, n / 2 ) == 0;
}
return double_string;
}
That is the function at first checks that the passed string is not empty and its length is an even number. If so then the function compares two halves of the string.
Here is a demonstration program.
#include <stdio.h>
#include <string.h>
int doubleString( const char *s )
{
int double_string = 0;
size_t n = 0;
if (( double_string = *s != '\0' && ( n = strlen( s ) ) % 2 == 0 ))
{
double_string = memcmp( s, s + n / 2, n / 2 ) == 0;
}
return double_string;
}
int main( void )
{
printf( "doubleString( \"\" ) = %d\n", doubleString( "" ) );
printf( "doubleString( \"HelloHello\" ) = %d\n", doubleString( "HelloHello" ) );
printf( "doubleString( \"Hello Hello\" ) = %d\n", doubleString( "Hello Hello" ) );
}
The program output is
doubleString( "" ) = 0
doubleString( "HelloHello" ) = 1
doubleString( "Hello Hello" ) = 0
Pay attention to that the function parameter should have the qualifier const because the passed string is not changed within the function. And you will be able to call the function with constant arrays without the need to defined one more function for constant character arrays.
it's better to do it with a while loop since you don't always have to iterate through all the elements of the string but since you want the for loop version here it is (C++ version):
int doubleString(string s){
int s_length = s.length();
if(s_length%2 != 0) {
return 0;
}
for (int i = 0; i < s_length/2; i++) {
if (s[i] != s[s_length/2 + i]){
return 0;
}
}
return 1;
}

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++.

Function to search for string in array of strings

I am trying to write a function that searches for the unique part(maximum two characters) of a string in an array of strings. Although strstr and strchr are not working and crash my program for some reason. So I have resorted to trying to create something that resembles their function.
My question is this:
Why is strstr not working (something like strstr(lex[j],word)) and what am I doing wrong here?
Here is the code for the function that searches for two unique characters within an array of strings :
void convert(char word[])
{
int i;
for (i = 0 ; i <= strlen(word) ; i++)
{
if(word[i] >= 65 && word[i] <= 90)
{
word[i] = word[i]+32;
}
}
}
int twochar(char lex[50][50],char word[], int size,char temp[3])
{
int i,j,k,count,totlen;
convert(word);
for (i = 0 ; i < strlen(word) - 1 ; i++)
{
count = 0;
totlen = 0;
for(j = 0; j<size; j++)
{
convert(lex[j]);
totlen += strlen(lex[j]) - 1;
for(k = 0 ; k < strlen(lex[j]) - 1 ; k++)
{
if (word[i] != lex[j][k] || word[i+1] != lex[j][k + 1])
{
count++;
}
}
}
if(count = = totlen)
{
temp[0] = word[i];
temp[1] = word[i+1];
}
}
}
int main(int argc, char *argv[])
{
char lex[50][50] = {"word1","word2","word3","word4" }, word[] = "test";
char p[3];
twochar(lex,word,4,p);
printf("%c%c\n",p[0],p[1]);
return 0;
}
this line:
for(k=0;k<strlen(lex[j])-1;k++)
is the problem.
strlen(lex[0]) is 0
strlen(lex[0])-1 is -1 (0xFFFFFFFF in a 32 bit system)
k starts at 0 and is incremented until it is equal to 0xFFFFFFFF
of course, k exceeds the bounds of lex[0] when k = 50.
the result is undefined behaviour which leads to the seg fault event
To determine all the above, I compiled/linked the program via gcc, with the -ggdb parameter.
then I ran the program via 'gdb theprogram'
within gdb I entered
br main <-- break point set
run
c <-- continue
the program then crashed with a seg fault event
then I entered
bt <-- back trace
the bt showed me this line: 'if(word[i]!=lex[j][k] || word[i+1]!=lex[j] [k+1])'
Then I entered
p k <-- print variable k
=6832 (which is WAY out of bounds)
then I entered
run
y
br theprogram.c:41 (the line number from above) <-- set another break epoint
c
the program stopped at line 41
p j
=0 ( this was the gdb response )
p k
= 0
p i
= 0
a little thinking,
stepping though that inner loop using 'n' <-- next
and playing on gdb
indicated that the problem was in line 42
and resulted in revealing the root of the problem

getting the length of initiated values in a character array

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' )

search for '\n in char pointer use c

I am trying to loop a char*str use this to find out how many lines:
char *str = "test1\ntest2\ntest3";
int lines = 0;
for(int i = 0 ; i < ?? ; i ++ )
{
if(str[i] == '\n') {
lines++;
}
}
I am not sure what to put at the ??, the question is :
1.I mean do I need to use strlen(str) + 1 ?
2.when the str is "test1\ntest2\ntest3\n",does the code still calculate correct lines?
I am using gcc by the way,thanks
every literal string ends with \0 which is a null character..It depicts the end of the string
So,
You can do this
for(int i = 0 ; str[i]!='\0' ; i ++ )
To extend the already-existent good answers: the idiomatic way for looping through a C string is
const char *s = "abc\ndef\nghi\n";
int lines = 0;
int nonempty = 0;
while (*s) {
nonempty = 1;
if (*s++ == '\n') lines++;
}
If you don't want to count the last empty line as a separate line, then add
if (nonempty && s[-1] == '\n' && lines > 0) lines--;
after the while loop.
Take the length of the string and iterate through all characters.
const unsigned long length=strlen(str);
for(int i = 0 ; i < length ; i ++ )
{
if(str[i] == '\n') {
lines++;
}
}
The following will deliver the same result regardless if the last character is a newline or not.
char *abc = "test1\ntest2\ntest3";
int lines = 0;
{
bool lastWasNewline = true;
char * p = abc;
for (; *p; ++p) {
if (lastWasNewline) ++lines;
lastWasNewline = *p == '\n';
}
}
1.I mean do I need to use strlen(str) + 1 ?
no, just use str[i] for i < ??, this tests if that is the 0 character which terminates the string
2.when the abc is "test1\ntest2\ntest3\n",does the code still calculate correct lines?
no, you code assumes that the input is broken into one input line per buffer line[j].
in place of ?? put strlen(abc) and make sure #include <string.h>
For better efficiency do
int length= strlen(abc);
and then use i < length
Or use str[i]!= '\0'

Resources