Run length encode in C, Problem with strcat - c

I'm trying to write a run-length encoding program in C.
For the input 'ABBCD' I expect the following result: 'A1B2C1D1'
I hand over a two-dimensional char array line for line to the function that encodes the characters:
for(i; i <= curline; i++) //hand over line for line
{
encoded->lines[i] = malloc(255);
encoded->lines[i] = rle_encode(read->lines[i]); //read->lines contains the characters of each line
printf("%s", encoded->lines[i]); // print out the result returned by the function rle_encode
}
I have tested this and know that it would work.
Now this is my function rle_encode:
char *rle_encode(char *line){
char *encode = malloc(sizeof(2 * strlen(line) + 1));
char prev = line[0]; //here I want to save the previous character
int i = 0;
int z = 1;
do{
i++;
if(prev == line[i]) // if character n equals n-1 (previous)
{
z++; // increase counter varaible z
}else
{
strcat( encode, line[i] ); //the content of line[i] will be append to the array encode
strcat( encode, z ); //also the counter variable will be appended
}
prev = line[i];
}while(line[i] != '\n'); //in the end of each line a '\n' appears, if line[i] is '\n' it should stop the function
return encode;}
What is wrong in function rle_encode?

malloc(sizeof(encode))
sizeof(encode) is the size of a pointer, so you allocate for it only 4 or 8 bytes.
I think that you also have to start the counters i and z from 0, not from 1.
EDIT:
There are many problems, I did not mark them all.

This is not a complete answer to your question because there are many other issues in your code.
This small program shows how to append a char to a string and how to append the decimal representation of an int to a string.
#include <stdio.h>
#include <string.h>
int main(void)
{
char encode[100] = "abc";
printf("%s\n", encode);
// append the char 'X' to the encode string
int len = strlen(encode);
encode[len] = 'X';
encode[len + 1] = 0; // put the NUL terminator
printf("%s\n", encode);
// append the decimal representation of the int y to encode
int y = 123;
char *p = encode + strlen(encode);
sprintf(p, "%d", y);
printf("%s\n", encode);
}
Output:
abc
abcX
abcX123
You really need to learn the basics of C.

Related

Why when my input is 8 or more characters long, symbols appear after printing the 8 character?

When I print 8 or more characters, symbols always print after the 8th character. Does anyone know what is wrong with the code and how can I fix this?
I've tried with different numbers of characters and it always happens when is more than 8 or 8.
#include <stdio.h>
int main() {
char ch = 0;
char temp[100];
int i = 0;
while (scanf("%c", &ch) == 1) {
if (ch != '\n') {
temp[i] = ch;
printf("%s", temp);
i++;
}
}
return 0;
}
My expected result is
1 12 123 123412345123456123456712345678
My actual output is
1 12 123 123412345123456123456712345678xxx
the x represent the symbols
The reason you get funny characters in the output is the temp array is not a proper C string because it is uninitialized so there is not necessarily a null byte '\0' after the ith entry set with temp[i] = ch;.
There are different ways to fix this problem:
you can initialize temp this way: char temp[100] = { 0 };
you can set the byte at temp[i+1] to '\0' in the loop.
Note also that the expected output is not 1 12 123 123412345123456123456712345678, but 112123123412345123456123456712345678 because you do not output a separator between the strings. It would be less confusing to output the strings on separate lines.
Finally scanf() will not return until the user has typed a newline because of buffering performed by the terminal driver and the standard input stream.
Here is a modified version:
#include <stdio.h>
int main() {
char ch;
char temp[100];
size_t i = 0;
while (scanf("%c", &ch) == 1 && i + 2 < sizeof(temp)) {
if (ch != '\n') {
temp[i] = ch;
temp[i + 1] = '\0';
printf("%s", temp);
i++;
}
}
return 0;
}
#chqrlie well explained and offered 2 alternatives.
3rd alternative: change format
printf("%s\n", temp) expects temp to be a string. In C, a string has a null character, else it is not a string.
Code failed to ensure a '\0' in temp[]. The result is undefined behavior (UB).
Code could use a precision to limit the number of characters printed with "%s".
// printf("%s", temp);
printf("%.*s", (int)i, temp);
"%.*s", (int)i, temp will print up to i characters or up to '\0' - which ever comes first. i is cast as (int) because printf expects an int for the precision given as an extra argument as specified by the .* before the s.
int main(void) {
char temp[100];
size_t i = 0;
while (i < sizeof temp && scanf("%c", &temp[i]) == 1 && temp[i] != '\n') {
i++;
}
printf("<%.*s>\n", (int)i, temp);
return 0;
}

Concatenation of first halves of two separate strings

How can I write C-program which accepts two strings from the user and prints a string which is the result of the concatenation of the first half of the two strings. For odd length strings, extra character goes in the first half of the string.
I have this so far but am confused on the splitting in half part...
printf("Please enter your first word.\n"); //Asks for first string
scanf("%s",&c); //Takes first string
printf("Please enter your second word.\n"); //Asks for second string
scanf("%s",&d); //Takes second string
strcat(c,d); //Combines both strings
If you just want to print out the result not caring about the content of the strings c and d any more you could do something like
#include <stdio.h>
#include <string.h>
int main(void) {
char c[1024]; // c string buffer
char d[1024]; // d string buffer
// initialize to empty strings
c[0] = '\0';
d[0] = '\0';
// read strings c and d
scanf("%s", c);
scanf("%s", d);
// just to make sure there is no overflow
c[1023] = '\0';
d[1023] = '\0';
// cut strings in middle
c[(strlen(c) + 1)/2] = '\0';
d[(strlen(d) + 1)/2] = '\0';
// print final string
printf("%s", c);
printf("%s\n", d);
return 0;
}
The result of (strlen(c) + 1)/2 does what you want because it performs an integer division. If strlen(c) gives an even size then adding 1 would make it the next odd with no effect on the integer division. If on the other hand the number is odd adding one will make it the next even achieving the rounding up you need. The '\0' will make sure that the string is terminated at that point.
If you don't want to loose the information of the two strings or need the resulting string stored then you could do something like
#include <stdio.h>
#include <string.h>
int main(void) {
char c[1024]; // c string buffer
char d[1024]; // d string buffer
char r[1024]; // resulting string buffer
int i; // general counter
int c_half_len; // c half length
int d_half_len; // d half length
// initialize to empty strings
c[0] = '\0';
d[0] = '\0';
r[0] = '\0';
// read strings c and d
scanf("%s", c);
scanf("%s", d);
// just to make sure there is no overflow
c[1023] = '\0';
d[1023] = '\0';
// get c and d half lengths rounding up
c_half_len = (strlen(c) + 1)/2;
d_half_len = (strlen(d) + 1)/2;
// copy first half c string to begining of result
for (i = 0; i < c_half_len; ++i) {
r[i] = c[i];
}
// copy first half d string after the end of the first half string
for (i = 0; i < d_half_len; ++i) {
r[c_half_len + i] = d[i];
}
// add an end of string character
r[c_half_len + d_half_len] = '\0';
// print final string
printf("%s\n", r);
return 0;
}
In both cases I assume that the two strings have a maximum length, in this case 1024 (including the end of string character). If that is not the case then you will need to handle things using dynamic memory.
void concathalf(const char *a, const char *b, char *out)
{
char *abuf, *bbuf;
if ((abuf = malloc(strlen(a) / 2)) && (bbuf = malloc(strlen(b) / 2))) {
memcpy(abuf, a, strlen(a) / 2);
memcpy(bbuf, b, strlen(b) / 2);
abuf[strlen(a) / 2] = bbuf[strlen(b) / 2] = 0;
}
sprintf(out, "%s%s", abuf, bbuf);
free(abuf);
free(bbuf);
}
Now, handling odd length inputs will be left as an exercise.

Array of dynamically allocated strings

This program is supposed to dynamically store each string entered into a pointer. Each pointer is part of an array of pointers that will collectively hold all of the strings. When the user enter an empty word, or NULL, it is supposed to quit. My problem is that the code just skips over the NULL conditional statement. I saw some similar posts and have been at it for hours but just can't solve it.
#include <stdio.h>
#include <string.h>
void readWord(char wordChar[], int MAX_CHARS);
int main()
{
int MAX_CHARS = 20;
int wCount = 0;
char *wordArray[wCount]; // Array of pointers that will each point to wordChar
char wordChar[MAX_CHARS];
int i;
for(i = 0;;i++)
{
wCount++;
printf("Enter word: ");
readWord(wordChar, MAX_CHARS); //Reads one word at a time
//Dynamically store each
wordArray[i] = (char*) malloc((int) strlen(wordChar) * (int) sizeof(char));
wordArray[i] = wordChar;
printf("%s \n", wordArray[i]); //Troubleshooting *********************
// If loop ends scanning when word is NULL
if(wordArray[i] == 'NULL')
{
printf("if loop");
break;
}
else printf("no loop");
}
}
/***********************************************************/
void readWord(char wordChar[], int MAX_CHARS)
{
int letter, i = 0;
while((letter = getchar()) != '\n')
{
if(i < MAX_CHARS)
{
wordChar[i] = letter;
i++;
}
}
wordChar[i] = '\0';
}
The short and useless summary is: you're #includeing string.h; use it!
You're trying to compare two pointers directly.
if(wordArray[i] == 'NULL')
This line looks at the pointer value of wordArray[i] to the value of the multi-character literal 'NULL' (note that I didn't say string: you used single quotes here, so 'NULL' has the integer value 0x4e554c4c; see https://stackoverflow.com/a/7459943/510299). If wordArray[i] points to the address 0x12345678, then this is comparing 0x12345678 to 0x4e554c4c and sees that they're not equal.
What you want is to compare strings. In C, you can't do this with == because C strings are char arrays or pointers to chars; == compares the pointer (address) value, as I noted above.
Solution, use strcmp.
if(strcmp(wordArray[i], "NULL") == 0)
(Note the use of double quotes.)
EDIT: Also note that char *wordArray[wCount]; is declared when wCount == 0. This nominally means you tried to declare an array of length 0, which is undefined behaviour. You need to declare wordArray with some length (probably the maximum number of words you can store). [Thanks to riodoro1 for pointing this out in a comment.]
You made a similar blunder with string manipulation in C here:
wordArray[i] = (char*) malloc((int) strlen(wordChar) * (int) sizeof(char));
This line sets the pointer wordArray[i] to some newly allocated memory.
wordArray[i] = wordChar;
This line then proceeds to change the pointer wordArray[i] to point to the original location where the read word was stored. Oops. The next time you go through this loop, wordChar changes, and wordArray[i] is pointing to wordChar... so the new word "replaces" all the previous words.
Solution? You need to copy the string to the memory you just malloc'd. Use strcpy().
printf("if loop");
A conditional (if) statement is not a kind of loop.
#include <stdio.h>
#include <stdlib.h> //for realloc and free (malloc)
#include <string.h>
void readWord(char wordChar[], int MAX_CHARS);
int main(void){
int MAX_CHARS = 20;
int wCount = 0;
char **wordArray = NULL; // Array of pointers that will each point to wordChar
char wordChar[MAX_CHARS];
int i;
for(i = 0;;i++){
printf("Enter word: ");
readWord(wordChar, MAX_CHARS); //Reads one word at a time
if(*wordChar == '\0' || strcmp(wordChar, "NULL") == 0){//empty word or "NULL"
putchar('\n');
break;
}
wCount++;
wordArray = realloc(wordArray, wCount * sizeof(*wordArray));//check omitted
//Dynamically store each
wordArray[i] = malloc(strlen(wordChar) + 1);//+1 for NUL
strcpy(wordArray[i], wordChar);//copy string
}
//check print and free
for(i = 0; i < wCount; ++i){
printf("'%s'\n", wordArray[i]);
free(wordArray[i]);
}
free(wordArray);
return 0;
}
void readWord(char wordChar[], int MAX_CHARS){
int letter, i = 0;
while((letter = getchar()) != '\n' && letter != EOF){
if(i < MAX_CHARS -1)//-1 for NUL, or char wordChar[MAX_CHARS+1];
wordChar[i++] = letter;
else
;//drop letter upto newline
}
wordChar[i] = '\0';
}

Converting string to number in C

I'm trying to write a program which converts lower cased alphabet to numerical digits.
a -> 01
b -> 02
...
z -> 26
For the first nine letters I need to put a 0 before the number.
This is my code.
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define MAXLEN 128
void s2n(char str[])
{
int i;
char x;
char result[256];
for (i=0; str[i] != '\0'; i++) {
x = str[i];
x = x - 96;
if (x < 10) {
char src[2] = {0, x};
strcat(result, src);
}
else {
char src2[1] = {x};
strcat(result, src2);
}
printf("%s", result);
}
}
int main(void)
{
char str[MAXLEN];
printf("Lower cased string please: ", MAXLEN);
scanf("%s", str);
s2n(str);
return 0;
}
Could you tell me what is wrong with my code??
One problem I see is:
char src[2] = {0, x};
You want to use the character 0, rather than the byte value 0 (NUL):
char src[2] = {'0', x};
Also, you need to NUL terminate your src array:
char src[] = {'0', x, 0};
The NUL termination would need to be done in both cases.
Another problem is your x = x - 96 statement also does not take into account that the character 0 is different from the byte value 0. So
x = x - 96 + '0';
would be better.
You use strcat() on an uninitialized array, result, it doesn't work that way, strcat() looks for the terminating nul byte in it's first parameter, and glues the second parameter from that point.
In your case there is no '\0' in result, calling strcat() with result as the first parameter causes undefined behavior.
You should at least ensure that there is one '\0' in result, you can do that by just setting the first element of result to '\0', like
result[0] = '\0';
Right before the loop starts, also you pass the second paramter src which is an array but is not a string, because it has no terminating '\0', but you actually don't need an array nor strcat().
You can use an index variable and just assing the ith element of the array to the actual character computed from the original value, like
result[i] = x;
Then you don't nul terminate result, which causes undefined behavior when you try to print resutl.
You also passing a parameter to printf() where it's not expecting one, that indicates that you are either silencing or ignoring compiler warnings.
There are many problems in your code, the following code, does what you want
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void s2n(char chr)
{
char result[4];
if (snprintf(result, sizeof(result), "%02d", 1 + chr - 'a') >= sizeof(result))
return;
printf("%s", result);
}
int main(void)
{
char chr;
printf("Lower cased string please: ");
if (scanf(" %c", &chr) != 1)
{
fprintf(stderr, "input error!\n");
return -1;
}
s2n(chr);
return 0;
}
note that no strings are required except the one where you are going to store the result, which you can build easily with sprintf().

Trying to remove all numbers from a string in C

I'm trying to take all of the numbers out of a string (char*)...
Here's what I have right now:
// Take numbers out of username if they exist - don't care about these
char * newStr;
strtoul(user, &newStr, 10);
user = newStr;
My understanding is that strtoul is supposed to convert a string to an unsigned long. The characters that are not numbers are put into the passed in pointer (the 2nd arg). When i reassign user to newStr and print it, the string remains unchanged. Why is this? Does anyone know of a better method?
From the documentation example:
#include <stdio.h>
#include <stdlib.h>
int main()
{
char str[30] = "2030300 This is test";
char *ptr;
long ret;
ret = strtoul(str, &ptr, 10);
printf("The number(unsigned long integer) is %lu\n", ret);
printf("String part is |%s|", ptr);
return(0);
}
Let us compile and run the above program, this will produce the following result:
The number(unsigned long integer) is 2030300
String part is | This is test|
char* RemoveDigits(char* input)
{
char* dest = input;
char* src = input;
while(*src)
{
if (isdigit(*src)) { src++; continue; }
*dest++ = *src++;
}
*dest = '\0';
return input;
}
Test:
int main(void)
{
char inText[] = "123 Mickey 456";
printf("The result is %s\n", RemoveDigits(inText));
// Expected Output: " Mickey "
}
The numbers were removed.
Here is a C program to remove digits from a string without using inbuilt functions. The string is shifted left to overwrite the digits:
#include <stdio.h>
int main(void) {
char a[] = "stack123overflow";
int i, j;
for (i = 0; a[i] != '\0'; i ++) {
if (a[i] == '0' || a[i] == '1' || a[i] == '2' || a[i] == '3' || a[i] == '4' || a[i] == '5' || a[i] == '6' || a[i] == '7' || a[i] == '8' || a[i] == '9') {
for (j = i; a[j] != '\0'; j ++)
a[j] = a[j + 1];
i--;
}
}
printf("%s", a);
return 0;
}
Example of execution:
$ gcc shift_str.c -o shift_str
$ ./shift_str
stackoverflow
strtoul() does not extract all numbers from string, it just trying to covert string to number and convertion stops when non digit is find. So if your string starts from number strtoul() works as you expect, but if string starts from letters, strtoul() stops at the first symbol. To solve your task in simple way you should copy all non-digits to other string, that will be a result.
The problem you are having is that strtoul is converting characters at the beginning of the string into an unsigned long. Once it encounters non-numeric digits, it stops.
The second parameter is a pointer into the original character buffer, pointing at the first non-numeric character.
http://www.cplusplus.com/reference/cstdlib/strtoul/
Parameter 2 : Reference to an object of type char*, whose value is set by the function to the next character in str after the numerical value.
So, if you tried to run the function on "123abc567efg" the returned value would be 123. The original string buffer would still be "123abc567efg" with the second parameter now pointing at the character 'a' in that buffer. That is, the pointer (ptr) will have a value 3 greater than original buffer pointer (str). Printing the string ptr, would give you "abc567efg" as it simply points back into the original buffer.
To actually remove ALL the digits from the string in C you would need to do something similar to this answer : Removing spaces and special characters from string
You build your allowable function to return false on 0-9 and true otherwise. Loop through and copy out digits to a new buffer.

Resources