I am doing a school C project. In the project , I have 48 characters hold in char holdReference[48] and every 8 of them must form 1 string. Thus, for example:
holdReference[0] = '0';
holdReference[1] = '0';
holdReference[2] = '0';
holdReference[3] = '0';
holdReference[4] = '1';
holdReference[5] = '2';
holdReference[6] = 'd';
holdReference[7] = '8';
....
Result strings formed by 8 characters hold in char HexReference[6][9] which means that HexReference holds 6 strings which have 8-bit length.
Here is my code:
char HexReference[6][9];
int hx = 0;
int indexxx;
int hex = -1;
while(hx<charNumber)
{
if(hx%8 == 0)
{
indexxx = 0;
hex++;
HexReference[hex][indexxx] = holdReference[hx];
indexxx++;
}
else
{
HexReference[hex][indexxx] = holdReference[hx];
indexxx++;
}
hx++;
}
printf("%s" , HexReference[0]); --> prints 000012d8/000017f3
Problem is that even if HexReference[0] must hold 000012d8 , 000012d8/000017f3 is printed on the console. 000017f3 must be hold in HexReference[1].
I will be very thankful if you help me soon.
You forgot to allocate enough space for the null-terminator "\0" at the end of each string.
And also since you are putting the chars one by one you also need to add the null-terminator manually.
the reason could be you did not added '\0' after first row data end so that is why second row string is printed with that
This should work
char HexReference[6][10];
int hx = 0;
int indexxx;
int hex = -1;
while(hx<charNumber)
{
if(hx%8 == 0)
{
indexxx = 0;
hex++;
HexReference[hex][indexxx] = holdReference[hx];
HexReference[hex][10] =0;
indexxx++;
}
else
{
HexReference[hex][indexxx] = holdReference[hx];
indexxx++;
}
hx++;
}
printf("%s" , HexReference[0]);
Related
I am currently dealing with a problem that especially has something to do with the first and second ASCII characters, the NULL Character and SOH Character.
The goal of this code is to send some characters and save them in a Tag, which contains 32 Bits/4 Bytes Blocks where Data can be saved in.
I know that there are better ways to achieve this. My Code functions nearly properly except in one single case:
When the Character equals the first ASCII character NULL. Which means when I view the value of the character: c_Char="", when this get sent to the Tag, it doesnt count as an ascii character and gets skipped.
Which means when I check which Characters are sent, the Buffer does not return the character with the 0 decimal value since it was not saved and got skipped.
Is there any If-Condition that I can use to make my program count the NULL ascii character?
This is part of the main Code:
// Splitting the 32 bits from B0 to 4 Bytes
Daten_EEPROM_Byte_VERTEILER(B0);
// Converting The four 32 Bits/4 Bytes Variables into 4 different decimal numbers
Data_Converting_binary_decimal(cFirst_Byte,&i_Char1);
Data_Converting_binary_decimal(cSecond_Byte,&i_Char2);
Data_Converting_binary_decimal(cThird_Byte,&i_Char3);
Data_Converting_binary_decimal(cFourth_Byte,&i_Char4);
//Converting the 4 decimal numbers into 4 ascii Chars.
Fmt(c_Char1,"%c<%i", i_Char1);
Fmt(c_Char2,"%c<%i",i_Char2);
Fmt(c_Char3,"%c<%i",i_Char3);
Fmt(c_Char4,"%c<%i",i_Char4);
//Converting Ascii characters into hexadecimal numbers.
DATEN_Umwandlungsfunktion_Char_hex (c_Char1, x_char1, &iSeriennummer);
DATEN_Umwandlungsfunktion_Char_hex (c_Char2, x_char2, &iSeriennummer);
DATEN_Umwandlungsfunktion_Char_hex (c_Char3, x_char3, &iSeriennummer);
DATEN_Umwandlungsfunktion_Char_hex (c_Char4, x_char4, &iSeriennummer);
//Putting the 4 hex numbers into the one variable:
Fmt(x_Result_B0,"%s<%s%s%s%s",x_char1,x_char2,x_char3,x_char4);
//Showing the 4 hex numbers in a panel:
SetCtrlAttribute(sPanels.P_Hauptmenue, P_MAIN_WB0, ATTR_CTRL_VAL, x_Result_B0);
memset(x_char1,0,sizeof(x_char1));
memset(x_char2,0,sizeof(x_char2));
memset(x_char3,0,sizeof(x_char3));
memset(x_char4,0,sizeof(x_char4));
//Sending the 4 characters into a MSP430 Port to save them in a tag through an antenna
Fmt(Result_Block0,"%s<%s%s%s%s",c_Char1,c_Char2,c_Char3,c_Char4);
Fmt(cCommand,"%s<%s%s%s%s",WRITE_BLOCK,"0_",Result_Block0,ENDE);
// Write and Read Data in and from Block 0
iResult = Befehl_Senden(cCommand,cAnswer);
Fmt(cCommand,"%s<%s%s%s",READ_BLOCK,"0",ENDE);
iResult = Befehl_Senden(cCommand,cAnswer);
CopyBytes(cRead_Block_0,0,cAnswer,23,8);
SetCtrlAttribute(sPanels.P_Hauptmenue, P_MAIN_BR0, ATTR_CTRL_VAL, cRead_Block_0);
These are the following functions that are used to convert the variables:
char *decimal_to_binary(int n)
{
int c, d, t;
char *p;
t = 0;
p = (char*)malloc(32+1);
if (p == NULL)
exit(EXIT_FAILURE);
for (c = 31 ; c >= 0 ; c--)
{
d = n >> c;
if (d & 1)
*(p+t) = 1 + '0';
else
*(p+t) = 0 + '0';
t++;
}
*(p+t) = '\0';
return p;
}
void Daten_HILFSFUNKTION_binary_decimal (char *cEingang, int *iAusgang)
{
int multiplier = 0;
int i;
int sum = 0;
int length;
char cMonth[10] = {0};
int iMonth;
length = StringLength (cEingang);
for (i=length-1; i>=0; i--)
{
CopyBytes (cMonth, 0, cEingang, i, 1);
Fmt (&iMonth, "%x<%s", cMonth);
sum = sum +(iMonth*pow(2, multiplier));
multiplier = multiplier + 1;
}
Fmt (iAusgang, "%i<%i", sum);
}
void Daten_EEPROM_Byte_VERTEILER(char *B)
{
CopyBytes(cFirst_Byte, 0,B,0,8);
CopyBytes(cSecond_Byte, 0,B,8,8);
CopyBytes(cThird_Byte, 0,B,16,8);
CopyBytes(cFourth_Byte, 0,B,24,8);
}
char *Daten_EEPROM_HILFSFUNKTION(char *Char_in_Bits, char *c_8Bits)
{
int Decimal = 0;
char c_Character[5] = {0};
CopyString(Char_in_Bits, 0,c_8Bits,0,8);
Daten_HILFSFUNKTION_binary_decimal (Char_in_Bits, &Decimal);
int B_1_dec = Decimal;
Fmt(c_Character,"%c<%i",B_1_dec);
memset(Char_in_Bits,0,sizeof(Char_in_Bits));
return c_Character;
}
void DATEN_alle_Char_uerbergabe_Funktion (char *Byte_Block,char *c_Char1, char *c_Char2, char *c_Char3,char * c_Char4)
{
DATEN_erster_Char_uebergabe_Funktion(Byte_Block, c_Char1);
DATEN_zweiter_Char_uebergabe_Funktion(Byte_Block, c_Char2);
DATEN_dritter_Char_uebergabe_Funktion(Byte_Block, c_Char3);
DATEN_vierter_Char_uebergabe_Funktion(Byte_Block, c_Char4);
}
char DATEN_erster_Char_uebergabe_Funktion (char *Byte_Block,char *c_Char1)
{
return* c_Char1 = *Daten_EEPROM_HILFSFUNKTION(Byte_Block, cFirst_Byte);
}
char DATEN_zweiter_Char_uebergabe_Funktion(char *Byte_Block,char *c_Char2)
{
return *c_Char2 = *Daten_EEPROM_HILFSFUNKTION(Byte_Block, cSecond_Byte);
}
char DATEN_dritter_Char_uebergabe_Funktion(char *Byte_Block,char *c_Char3)
{
return *c_Char3 = *Daten_EEPROM_HILFSFUNKTION(Byte_Block, cThird_Byte);
}
char DATEN_vierter_Char_uebergabe_Funktion(char *Byte_Block,char *c_Char4)
{
return *c_Char4 = *Daten_EEPROM_HILFSFUNKTION(Byte_Block, cSecond_Byte);
}
void char_Umwandeln (char *cEingang,char *cAusgang)
{
int ilaenge;
int idez_Wert;
int iPos;
char cZwischenspeicher [5] = {0};
ilaenge = StringLength(cEingang);
for (iPos = 0; iPos <=ilaenge - 1; iPos++)
{
idez_Wert = 0;
//CopyBytes (cZwishcenspeicher, 0, cEingang, ilaenge-iPos,1);
CopyBytes (cZwischenspeicher,0,cEingang,iPos,1);
Scan (cZwischenspeicher,"%s>%i[r256]",&idez_Wert);
if (idez_Wert == 0)
{
CopyBytes (cAusgang, 0,"00",0,2);
}
else if (idez_Wert <16)
{
Fmt(cAusgang,"%s<%s%s%i[r16]",cAusgang,"0",idez_Wert);
}
else
{
Fmt(cAusgang,"%s<%s%i[r16]",cAusgang,idez_Wert);
}
}
StringUpperCase(cAusgang);
}
void DATEN_Umwandlungsfunktion_Char_hex (char *Char, char *hex_Char, int *dec_Nummer)
{
char_Umwandeln (Char,hex_Char);
Scan(&hex_Char,"%s>%x",&dec_Nummer);
}
If anyone has already had this problem and knows a solution for this issue, I would be so thankful. Thanks a lot in advance.
I have a problem with one of the test for my solution for challenge in codewars. I have to write a function that returns alphabet position of characters in input string. My solution is below. I pass all my test and also tests from codewars but fail on this one (I did not implement this test code it was pat of the test code implemented by code wars):
Test(number_tests, should_pass) {
srand(time(NULL));
char in[11] = {0};
char *ptr;
for (int i = 0; i < 15; i++) {
for (int j = 0; j < 10; j++) {
char c = rand() % 10;
in[j] = c + '0';
}
ptr = alphabet_position(in);
cr_assert_eq(strcmp(ptr, ""), 0);
free(ptr);
}
}
The error I receive is following: The expression (strcmp(ptr, "")) == (0) is false. Thanks for the help!
p.s Also I noticed that I am leaking memory (I don't know how to solve this so I suppose I would use array to keep track of string and don't use malloc) --> I suppose this is not an issue I would just free(ptr) in main function.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
char *alphabet_position(char *text);
// test
int main()
{
if (!strcmp("1 2 3", alphabet_position("abc")))
{
printf("success...\n");
}
else
{
printf("fail...\n");
}
if (!strcmp("", alphabet_position("..")))
{
printf("success...\n");
}
else
{
printf("fail...\n");
}
if (!strcmp("20 8 5 19 21 14 19 5 20 19 5 20 19 1 20 20 23 5 12 22 5 15 3 12 15 3 11", alphabet_position("The sunset sets at twelve o' clock.")))
{
printf("success...\n");
}
else
{
printf("fail...\n");
}
}
char *alphabet_position(char *text)
{
// signature: string -> string
// purpose: extact alphabet position of letters in input string and
// return string of alphabet positions
// return "123"; // stub
// track numerical value of each letter according to it's alphabet position
char *alph = "abcdefghijklmnopqrstuvwxyz";
// allocate maximum possible space for return string
// each char maps to two digit number + trailing space after number
char *s = malloc(sizeof(char) * (3 * strlen(text) + 1));
// keep track of the begining of return string
char *head = s;
int index = 0;
int flag = 0;
while(*text != '\0')
{
if ( ((*text > 64) && (*text < 91)) || ((*text > 96) && (*text < 123)))
{
flag = 1;
index = (int)(strchr(alph, tolower(*text)) - alph) + 1;
if (index > 9)
{
int n = index / 10;
int m = index % 10;
*s = n + '0';
s++;
*s = m + '0';
s++;
*s = ' ';
s++;
}
else
{
*s = index + '0';
s++;
*s = ' ';
s++;
}
}
text++;
}
if (flag != 0) // if string contains at least one letter
{
*(s -1) = '\0'; // remove the trailing space and insert string termination
}
return head;
}
Here is what I think is happening:
In the cases where none of the characters in the input string is an alphabet character, s is never used, and therefore the memory allocated by malloc() could be anything. malloc() does not clear / zero-out memory.
The fact that your input case of ".." passes is just coincidence. The codewars test case does many such non-alphabetical tests in a row, each of which causes a malloc(), and if any one of them fails, the whole thing fails.
I tried recreating this situation, but it's (as I say) unpredictable. To test this, add a debugging line to output the value of s when flag is still 0:
if (flag != 0) { // if string contains at least one letter
*(s -1) = '\0'; // remove the trailing space and insert string termination
}
else {
printf("flag is still 0 : %s\n", s);
}
I'll wager that sometimes you get a garbage / random string that is not "".
I made a code and my target is to put spacewhere the input word was found in a sentence.
i neet to replece the small word with space
like:
Three witches watched three watches
tch
output:
Three wi es wa ed three wa es
I made this code:
#include<stdio.h>
#define S 8
#define B 50
void main() {
char small[S] = {"ol"};
char big[B] = {"my older gradmom see my older sister"};
int i = 0, j = 0;
for (i = 0; i < B; i++)
{
for(j=0;j<S;j++)
{
if(small[j]!=big[i])
{
j=0;
break;
}
if(small[j]=='\0')
{
while (i-(j-1)!=i)
{
i = i - j;
big[i] = '\n';
i++;
}
}
}
}
puts(big);
}
First of all, in your exemple you work with newline '\n' and not with space.
Consider this simple example:
#include<stdio.h>
#define S 8
#define B 50
void main() {
char small[S] = {"ol"};
char big[B] = {"my older gradmom see my older sister"};
int i = 0, j = 0;
int cpt = 0;
int smallSize = 0;
// loop to retrieve smallSize
for (i = 0; i < S; i++)
{
if (small[i] != '\0')
smallSize++;
}
// main loop
for (i = 0; i < B; i++)
{
// stop if we hit the end of the string
if (big[i] == '\0')
break;
// increment the cpt and small index while the content of big and small are equal
if (big[i] == small[j])
{
cpt++;
j++;
}
// we didn't found the full small word
else
{
j = 0;
cpt = 0;
}
// test if we found the full word, if yes replace char in big by space
if (cpt == smallSize)
{
for (int k = 0; k < smallSize; k++)
{
big[i-k] = ' ';
}
j = 0;
cpt = 0;
}
}
puts(big);
}
You need first to retrieve the real size of the small array.
Once done, next step is to look inside "big" if there is the word small inside. If we find it, then replace all those char by spaces.
If you want to replace the whole small word with a single space, then you'll need to adapt this example !
I hope this help !
A possible way is to use to pointers to the string, one for reading and one for writing. This will allow to replace an arbitrary number of chars (the ones from small) with a single space. And you do not really want to nest loops but une only one to process every char from big.
Last but not least, void main() should never be used except in stand alone environment (kernel or embedded development). Code could become:
#include <stdio.h>
#define S 8
#define B 50
int main() { // void main is deprecated...
char small[S] = {"ol"};
char big[B] = {"my older gradmom see my older sister"};
int i = 0, j = 0;
int k = 0; // pointer to written back big
for (i = 0; i < B; i++)
{
if (big[i] == 0) break; // do not process beyond end of string
if(small[j]!=big[i])
{
for(int l=0; l<j; l++) big[k++] = small[l]; // copy an eventual partial small
big[k++] = big[i]; // copy the incoming character
j=0; // reset pointer to small
continue;
}
else if(small[++j] == 0) // reached end of small
{
big[k++] = ' '; // replace chars from small with a single space
j = 0; // reset pointer to small
}
}
big[k] = '\0';
puts(big);
return 0;
}
or even better (no need for fixed sizes of strings):
#include <stdio.h>
int main() { // void main is deprecated...
char small[] = {"ol"};
char big[] = {"my older gradmom see my older sister"};
int i = 0, j = 0;
int k = 0; // pointer to written back big
for (i = 0; i < sizeof(big); i++)
{
if(small[j]!=big[i])
...
In C strings are terminated with a null character '\0'. Your code defines a somehow random number at the beginning (B and S) and iterates over that much characters instead of the exact number of characters, the strings actually contain. You can use the fact that the string is terminated by testing the content of the string in a while loop.
i = 0;
while (str[i]) {
...
i = i + 1;
}
If you prefer for loops you can write it also as a for loop.
for (i = 0; str[i]; i++) {
...
}
Your code does not move the contents of the remaining string to the left. If you replace two characters ol with one character , you have to move the remaining characters to the left by one character. Otherwise you would have a hole in the string.
#include <stdio.h>
int main() {
char small[] = "ol";
char big[] = "my older gradmom see my older sister";
int s; // index, which loops through the small string
int b; // index, which loops through the big string
int m; // index, which loops through the characters to be modified
// The following loops through the big string up to the terminating
// null character in the big string.
b = 0;
while (big[b]) {
// The following loops through the small string up to the
// terminating null character, if the character in the small
// string matches the corresponding character in the big string.
s = 0;
while (small[s] && big[b+s] == small[s]) {
// In case of a match, continue with the next character in the
// small string.
s = s + 1;
}
// If we are at the end of the small string, we found in the
// big string.
if (small[s] == '\0') {
// Now we have to modify the big string. The modification
// starts at the current position in the big string.
m = b;
// First we have to put the space at the current position in the
// big string.
big[m] = ' ';
// And next the rest of the big string has to be moved left. The
// rest of the big string starts, where the match has ended.
while (big[b+s]) {
m = m + 1;
big[m] = big[b+s];
s = s + 1;
}
// Finally the big string has to be terminated by a null
// character.
big[m+1] = '\0';
}
// Continue at next character in big string.
b = b + 1;
}
puts(big);
return 0;
}
I am trying to separate each word from a character array and put them into a pointer array, one word for each slot. Also, I am supposed to use isspace() to detect blanks. But if there is a better way, I am all ears. At the end of the code I want to print out the content of the parameter array.
Let's say the line is: "this is a sentence". What happens is that it prints out "sentence" (the last word in the line, and usually followed by some random character) 4 times (the number of words). Then I get "Segmentation fault (core dumped)".
Where am I going wrong?
int split_line(char line[120])
{
char *param[21]; // Here I want to put one word for each slot
char buffer[120]; // Word buffer
int i; // For characters in line
int j = 0; // For param words
int k = 0; // For buffer chars
for(i = 0; i < 120; i++)
{
if(line[i] == '\0')
break;
else if(!isspace(line[i]))
{
buffer[k] = line[i];
k++;
}
else if(isspace(line[i]))
{
buffer[k+1] = '\0';
param[j] = buffer; // Puts word into pointer array
j++;
k = 0;
}
else if(j == 21)
{
param[j] = NULL;
break;
}
}
i = 0;
while(param[i] != NULL)
{
printf("%s\n", param[i]);
i++;
}
return 0;
}
There are many little problems in this code :
param[j] = buffer; k = 0; : you rewrite at the beginning of buffer erasing previous words
if(!isspace(line[i])) ... else if(isspace(line[i])) ... else ... : isspace(line[i]) is either true of false, and you always use the 2 first choices and never the third.
if (line[i] == '\0') : you forget to terminate current word by a '\0'
if there are multiple white spaces, you currently (try to) add empty words in param
Here is a working version :
int split_line(char line[120])
{
char *param[21]; // Here I want to put one word for each slot
char buffer[120]; // Word buffer
int i; // For characters in line
int j = 0; // For param words
int k = 0; // For buffer chars
int inspace = 0;
param[j] = buffer;
for(i = 0; i < 120; i++) {
if(line[i] == '\0') {
param[j++][k] = '\0';
param[j] = NULL;
break;
}
else if(!isspace(line[i])) {
inspace = 0;
param[j][k++] = line[i];
}
else if (! inspace) {
inspace = 1;
param[j++][k] = '\0';
param[j] = &(param[j-1][k+1]);
k = 0;
if(j == 21) {
param[j] = NULL;
break;
}
}
}
i = 0;
while(param[i] != NULL)
{
printf("%s\n", param[i]);
i++;
}
return 0;
}
I only fixed the errors. I leave for you as an exercise the following improvements :
the split_line routine should not print itself but rather return an array of words - beware you cannot return an automatic array, but it would be another question
you should not have magic constants in you code (120), you should at least have a #define and use symbolic constants, or better accept a line of any size - here again it is not simple because you will have to malloc and free at appropriate places, and again would be a different question
Anyway good luck in learning that good old C :-)
This line does not seems right to me
param[j] = buffer;
because you keep assigning the same value buffer to different param[j] s .
I would suggest you copy all the char s from line[120] to buffer[120], then point param[j] to location of buffer + Next_Word_Postition.
You may want to look at strtok in string.h. It sounds like this is what you are looking for, as it will separate words/tokens based on the delimiter you choose. To separate by spaces, simply use:
dest = strtok(src, " ");
Where src is the source string and dest is the destination for the first token on the source string. Looping through until dest == NULL will give you all of the separated words, and all you have to do is change dest each time based on your pointer array. It is also nice to note that passing NULL for the src argument will continue parsing from where strtok left off, so after an initial strtok outside of your loop, just use src = NULL inside. I hope that helps. Good luck!
I am new to programming in C and am trying to write a simple function that will normalize a char array. At the end i want to return the length of the new char array. I am coming from java so I apologize if I'm making mistakes that seem simple. I have the following code:
/* The normalize procedure normalizes a character array of size len
according to the following rules:
1) turn all upper case letters into lower case ones
2) turn any white-space character into a space character and,
shrink any n>1 consecutive whitespace characters to exactly 1 whitespace
When the procedure returns, the character array buf contains the newly
normalized string and the return value is the new length of the normalized string.
*/
int
normalize(unsigned char *buf, /* The character array contains the string to be normalized*/
int len /* the size of the original character array */)
{
/* use a for loop to cycle through each character and the built in c functions to analyze it */
int i;
if(isspace(buf[0])){
buf[0] = "";
}
if(isspace(buf[len-1])){
buf[len-1] = "";
}
for(i = 0;i < len;i++){
if(isupper(buf[i])) {
buf[i]=tolower(buf[i]);
}
if(isspace(buf[i])) {
buf[i]=" ";
}
if(isspace(buf[i]) && isspace(buf[i+1])){
buf[i]="";
}
}
return strlen(*buf);
}
How can I return the length of the char array at the end? Also does my procedure properly do what I want it to?
EDIT: I have made some corrections to my program based on the comments. Is it correct now?
/* The normalize procedure normalizes a character array of size len
according to the following rules:
1) turn all upper case letters into lower case ones
2) turn any white-space character into a space character and,
shrink any n>1 consecutive whitespace characters to exactly 1 whitespace
When the procedure returns, the character array buf contains the newly
normalized string and the return value is the new length of the normalized string.
*/
int
normalize(unsigned char *buf, /* The character array contains the string to be normalized*/
int len /* the size of the original character array */)
{
/* use a for loop to cycle through each character and the built in c funstions to analyze it */
int i = 0;
int j = 0;
if(isspace(buf[0])){
//buf[0] = "";
i++;
}
if(isspace(buf[len-1])){
//buf[len-1] = "";
i++;
}
for(i;i < len;i++){
if(isupper(buf[i])) {
buf[j]=tolower(buf[i]);
j++;
}
if(isspace(buf[i])) {
buf[j]=' ';
j++;
}
if(isspace(buf[i]) && isspace(buf[i+1])){
//buf[i]="";
i++;
}
}
return strlen(buf);
}
The canonical way of doing something like this is to use two indices, one for reading, and one for writing. Like this:
int normalizeString(char* buf, int len) {
int readPosition, writePosition;
bool hadWhitespace = false;
for(readPosition = writePosition = 0; readPosition < len; readPosition++) {
if(isspace(buf[readPosition]) {
if(!hadWhitespace) buf[writePosition++] = ' ';
hadWhitespace = true;
} else if(...) {
...
}
}
return writePosition;
}
Warning: This handles the string according to the given length only. While using a buffer + length has the advantage of being able to handle any data, this is not the way C strings work. C-strings are terminated by a null byte at their end, and it is your job to ensure that the null byte is at the right position. The code you gave does not handle the null byte, nor does the buffer + length version I gave above. A correct C implementation of such a normalization function would look like this:
int normalizeString(char* string) { //No length is passed, it is implicit in the null byte.
char* in = string, *out = string;
bool hadWhitespace = false;
for(; *in; in++) { //loop until the zero byte is encountered
if(isspace(*in) {
if(!hadWhitespace) *out++ = ' ';
hadWhitespace = true;
} else if(...) {
...
}
}
*out = 0; //add a new zero byte
return out - string; //use pointer arithmetic to retrieve the new length
}
In this code I replaced the indices by pointers simply because it was convenient to do so. This is simply a matter of style preference, I could have written the same thing with explicit indices. (And my style preference is not for pointer iterations, but for concise code.)
if(isspace(buf[i])) {
buf[i]=" ";
}
This should be buf[i] = ' ', not buf[i] = " ". You can't assign a string to a character.
if(isspace(buf[i]) && isspace(buf[i+1])){
buf[i]="";
}
This has two problems. One is that you're not checking whether i < len - 1, so buf[i + 1] could be off the end of the string. The other is that buf[i] = "" won't do what you want at all. To remove a character from a string, you need to use memmove to move the remaining contents of the string to the left.
return strlen(*buf);
This would be return strlen(buf). *buf is a character, not a string.
The notations like:
buf[i]=" ";
buf[i]="";
do not do what you think/expect. You will probably need to create two indexes to step through the array — one for the current read position and one for the current write position, initially both zero. When you want to delete a character, you don't increment the write position.
Warning: untested code.
int i, j;
for (i = 0, j = 0; i < len; i++)
{
if (isupper(buf[i]))
buf[j++] = tolower(buf[i]);
else if (isspace(buf[i])
{
buf[j++] = ' ';
while (i+1 < len && isspace(buf[i+1]))
i++;
}
else
buf[j++] = buf[i];
}
buf[j] = '\0'; // Null terminate
You replace the arbitrary white space with a plain space using:
buf[i] = ' ';
You return:
return strlen(buf);
or, with the code above:
return j;
Several mistakes in your code:
You cannot assign buf[i] with a string, such as "" or " ", because the type of buf[i] is char and the type of a string is char*.
You are reading from buf and writing into buf using index i. This poses a problem, as you want to eliminate consecutive white-spaces. So you should use one index for reading and another index for writing.
In C/C++, a native string is an array of characters that ends with 0. So in essence, you can simply iterate buf until you read 0 (you don't need to use the len variable at all). In addition, since you are "truncating" the input string, you should set the new last character to 0.
Here is one optional solution for the problem at hand:
int normalize(char* buf)
{
char c;
int i = 0;
int j = 0;
while (buf[i] != 0)
{
c = buf[i++];
if (isspace(c))
{
j++;
while (isspace(c))
c = buf[i++];
}
if (isupper(c))
buf[j] = tolower(c);
j++;
}
buf[j] = 0;
return j;
}
you should write:
return strlen(buf)
instead of:
return strlen(*buf)
The reason:
buf is of type char* - it's an address of a char somewhere in the memory (the one in the beginning of the string). The string is null terminated (or at least should be), and therefore the function strlen knows when to stop counting chars.
*buf will de-reference the pointer, resulting on a char - not what strlen expects.
Not much different then others but assumes this is an array of unsigned char and not a C string.
tolower() does not itself need the isupper() test.
int normalize(unsigned char *buf, int len) {
int i = 0;
int j = 0;
int previous_is_space = 0;
while (i < len) {
if (isspace(buf[i])) {
if (!previous_is_space) {
buf[j++] = ' ';
}
previous_is_space = 1;
} else {
buf[j++] = tolower(buf[i]);
previous_is_space = 0;
}
i++;
}
return j;
}
#OP:
Per the posted code it implies leading and trailing spaces should either be shrunk to 1 char or eliminate all leading and trailing spaces.
The above answer simple shrinks leading and trailing spaces to 1 ' '.
To eliminate trailing and leading spaces:
int i = 0;
int j = 0;
while (len > 0 && isspace(buf[len-1])) len--;
while (i < len && isspace(buf[i])) i++;
int previous_is_space = 0;
while (i < len) { ...