How to remove newline and instead add comma? - c

In this code, I want to remove the newline. It means whenever I print this variable, it should give me a string without a newline but instead, the comma should replace it. I can directly add a comma when declaring but I want a separate result.
Expecting output
This,is,a,simple,sentence
Code
#include <stdio.h>
#include <string.h>
int main(){
char str[] = "This\nis\na\nsimple\nsentence";
printf("%s\n", str);
}

A simple for loop will do it:
for (int i = 0; i < sizeof(str); i++)
if (str[i] == '\n')
str[i] = ',';
This modifies the original string, rather than creating a new one.

You can create a one-line while loop using the strchr() function from the standard library to replace each newline character with a comma:
#include <stdio.h>
#include <string.h>
int main()
{
char str[] = "This\nis\na\nsimple\nsentence";
char* np;
while ((np = strchr(str, '\n')) != NULL) *np = ',';
printf("%s\n", str);
return 0;
}
A more efficient way of searching through the string is to use the last-found position (while there is one) as the starting-point for the search in the next loop:
int main()
{
char str[] = "This\nis\na\nsimple\nsentence";
char* np = str;
while ((np = strchr(np, '\n')) != NULL) *np = ',';
printf("%s\n", str);
return 0;
}

Related

variable takes extra characters once exit the while loop, C language using malloc()

I solved this problem by using realloc(), which is more brief and easier to understand.
Though using malloc() is taking detour, it still helps to enhance my coding logic.
Below is the realloc() version.
char* getInput(char* inputStr)
{
int count = 1;
char *ch;
do{
count++;
fgets(ch, 2, stdin); //ch stores 1 char from user each time
inputStr = realloc(inputStr, (count+1)* sizeof(char));
strcat(inputStr, ch);
printf("in do inputStr=%s\n", inputStr);
}while(ch[0] != '\n');
inputStr[count] = '\0';
printf("in while inputStr=%s\n", inputStr);
return inputStr;
}
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Original question:
I'm new to C, and I'm in trouble with malloc function.
In my program, the user need to input a arbitrary long string, if there exists a space in the string, then string variable command will take the first part of the input string, variable filename will take the second part. e.g:
Input- read mydiary.txt
inputStr's data is read, command's data is mydiary.txt
I wrote a separate getComd.c file, the command will just take the first part of the inputStr, however, when I put functions getComd together with getInput, getComd will copy the whole getInput string, with the extra filename.
I've put some printf inside the code to help tracing.
I doubt if there is something to do with the variable scope, but I cannot detect the real problem.
Could anyone help me to explain what happened in my code?
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
char* getInput(void);
char* getComd(char* inputStr, char* comd);
int main(){
char* inputStr;
char* command;
char* filename;
printf("Input- ");
inputStr = getInput();
printf("inputStr=%s\n", inputStr);
command = getComd(inputStr, command);
return 0;
}
char* getInput()
{
char* str;
char* _str;
int i = 1; // 1 is for the first char to take;
str = malloc((i+1)*sizeof(char)); // i+1 is for the '\0'
str[i-1] = '\0';
while( '\n' != ( str[i-1] = getchar() ) )
{
i++;
_str = malloc(i*sizeof(char));
strcpy(_str, str);
free(str);
str = malloc((i+1)*sizeof(char));
strcpy(str, _str);
str[i-1] = '\0';
free(_str);
}
return str;
}
char* getComd(char* inputStr, char* comd)
{
comd=NULL;
char* _comd=NULL;
int i = 1; // 1 is to take 1st input char;
comd = malloc((i+1)*sizeof(char)); // i+1 is for the '\0'
printf("enter while loop\n");
while( ( comd[i-1] = inputStr[i-1] ) != ' '){
i++;
_comd = malloc(i*sizeof(char));
strcpy(_comd, comd);
free(comd);
comd = malloc((i+1)*sizeof(char));
strcpy(comd, _comd);
comd[i-1] = '\0';
free(_comd);
printf("comd=%s\n", comd);
}
printf("outside while loop, comd=%s\n", comd);
return comd;
}
Below is the independent getComd.c file
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(){
char* inputStr="hello world";
char* comd = NULL;
char* _comd = NULL;
int i = 1; // 1 is for the first char to take;
comd = malloc( (i+1)*sizeof(char) ); // i+1 is for the '\0'
printf("enter while loop\n");
while( ( comd[i-1] = inputStr[i-1] ) != ' '){
i++;
_comd = malloc(i*sizeof(char));
strcpy(_comd, comd);
free(comd);
comd = malloc((i+1)*sizeof(char));
strcpy(comd, _comd);
comd[i-1] = '\0';
free(_comd);
printf("comd=%s\n", comd);
}
printf("outside the while, comd=%s\n", comd);
return 0;
}

What is the difference between two ways to manipulate strings in C?

I want to copy a string "str" to p . First I used the code I commented out, but the output was empty. So I tried the code that is below the commented area, and it worked. What is the difference between the two methods to manipulate strings in C? Thanks in advance.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main(void)
{
char *str = "laekfja";
char *p = (char*)malloc(51 * sizeof(char));
//First try.
/* while(*str)
{
*p++ = *str++;
}
*p = '\0';
printf("%s\n", p);
*/
//Second try.
int i = 0;
while(i < strlen(str))
{
p[i] = str[i];
i++;
}
p[i] = '\0';
printf("%s\n", p);
return 0;
}
Both methods work to copy the string. The error in the first method is in printing the copied string out when the loop is complete:
printf("%s\n", p);
At this point, p is pointing to the last character inserted into the copy, the null character, not the beginning of the string. So the printf() correctly prints nothing.

String and String array Manipulation in c

I'm trying to write a string spliter function in C.It uses space as delimiter to split a given string in two or more. It more like the split funtion in Python.Here is the code:-
#include <stdio.h>
#include <string.h>
void slice_input (char *t,char **out)
{
char *x,temp[10];
int i,j;
x = t;
j=0;
i=0;
for (;*x!='\0';x++){
if (*x!=' '){
temp[i] = *x;
i++;
}else if(*x==' '){
out[j] = temp;
j++;i=0;
}
}
}
int main()
{
char *out[2];
char inp[] = "HEllo World ";
slice_input(inp,out);
printf("%s\n%s",out[0],out[1]);
//printf("%d",strlen(out[1]));
return 0;
}
Expeted Output:-
HEllo
World
but it is showing :-
World
World
Can you help please?
out[j] = temp;
where temp is a local variable. It will go out of scope as soon as your function terminates, thus out[j] will point to garbage, invoking Undefined Behavior when being accessed.
A simple fix would be to use a 2D array for out, and use strcpy() to copy the temp string to out[j], like this:
#include <stdio.h>
#include <string.h>
void slice_input(char *t, char out[2][10]) {
char *x, temp[10];
int i,j;
x = t;
j=0;
i=0;
for (;*x!='\0';x++) {
if (*x!=' ') {
temp[i] = *x;
i++;
} else if(*x==' ') {
strcpy(out[j], temp);
j++;
i=0;
}
}
}
int main()
{
char out[2][10];
char inp[] = "HEllo World ";
slice_input(inp,out);
printf("%s\n%s",out[0],out[1]);
return 0;
}
Output:
HEllo
World
http://www.cplusplus.com/reference/clibrary/cstring/strtok/
From the website:
char * strtok ( char * str, const char * delimiters ); On a first
call, the function expects a C string as argument for str, whose first
character is used as the starting location to scan for tokens. In
subsequent calls, the function expects a null pointer and uses the
position right after the end of last token as the new starting
location for scanning.
Once the terminating null character of str is found in a call to
strtok, all subsequent calls to this function (with a null pointer as
the first argument) return a null pointer.
Parameters
str C string to truncate. Notice that this string is modified by being
broken into smaller strings (tokens). Alternativelly [sic], a null
pointer may be specified, in which case the function continues
scanning where a previous successful call to the function ended.
delimiters C string containing the delimiter characters. These may
vary from one call to another. Return Value
A pointer to the last token found in string. A null pointer is
returned if there are no tokens left to retrieve.
Example
/* strtok example */
#include <stdio.h>
#include <string.h>
int main ()
{
char str[] ="- This, a sample string.";
char * pch;
printf ("Splitting string \"%s\" into tokens:\n",str);
pch = strtok (str," ,.-");
while (pch != NULL)
{
printf ("%s\n",pch);
pch = strtok (NULL, " ,.-");
}
return 0;
}
You can use this function to split string into tokens - there is no need to use some own functions. Your code looks like garbage, please format it.
Your source propably would look like this:
char *
strtok(s, delim)
char *s; /* string to search for tokens */
const char *delim; /* delimiting characters */
{
static char *lasts;
register int ch;
if (s == 0)
s = lasts;
do {
if ((ch = *s++) == '\0')
return 0;
} while (strchr(delim, ch));
--s;
lasts = s + strcspn(s, delim);
if (*lasts != 0)
*lasts++ = 0;
return s;
}

Trouble removing trailing newline from string

I'm having trouble removing the trailing \n from a multiple line string then into tokens to list them for a table. The string is coming from a text file using input redirection (< input.txt). This is what I have so far:
The text file is:
Little Boy Blue, Come blow your horn, The sheep's in the meadow, The
cow's in the corn; Where is that boy Who looks after the sheep? Under
the haystack Fast asleep. Will you wake him? Oh no, not I, For if I do
He will surely cry.
Code:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main()
{
int c;
char *line;
char *ptr;
char *pch;
line = (char *) malloc(1);
ptr = line;
for (;( *line = c = tolower(getchar())) != EOF; line++);
*line='\0';
pch = strtok(ptr," \n,.-");
while (pch != NULL)
{
printf ("%s\n", pch);
pch = strtok(NULL, " ?;,.-");
}
return 0;
}
You have major memory allocation problems; you allocate one byte of memory, and then try to read a large number of characters into it, and add an null byte at the end. You need to fix that.
Your code is also a little puzzling in that the delimiters change between the two calls to strtok(). That's allowed, but it isn't clear why you don't include newline in the second and question mark and semicolon in the first (and what about exclamation mark and colon?).
Note that tolower() is declared in <ctype.h>.
The simplest way to eliminate the newline at the end is to overwrite it with the null byte. If you need to map other newlines as well, do the translation as the data is read.
#include <ctype.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main(void)
{
int c;
char *line = (char *)malloc(1);
size_t l_max = 1;
char *ptr = line;
if (line == 0)
return 1; // Report out of memory?
while ((c = tolower(getchar())) != EOF)
{
if (ptr == line + l_max - 1)
{
char *extra = realloc(line, 2 * l_max);
if (extra == 0)
return 1; // Report out of memory?
l_max *= 2;
line = extra;
}
*ptr++ = c;
}
if (*(ptr - 1) == '\n')
ptr--;
*ptr = '\0';
static const char markers[] = " \n\t,.;:?!-";
char *pch = strtok(line, markers);
while (pch != NULL)
{
printf ("%s\n", pch);
pch = strtok(NULL, markers);
}
return 0;
}
You could also just leave the newline in the data; strtok() will end up skipping over it.

Updating string until period is found in C

In this function I am going to be receiving char * words such as
person.vet.blah
and
word.friends.joe
I want to extract the first word. So for the first one I want to extract
person
and the second one I want to extract
word
How can I correctly do this? Here is my code:
char *separate_name(char *machine_name)
{
//iterate until you find period. then return
char absolute_name[1000];
int i;
for (i =0; i < strlen(machine_name); i++)
{
if (machine_name[i] == '.')
absolute_name[i] = machine_name[i];
}
return absolute_name;
}
This is just segfaulting. Any ideas what I should be doing? machine_name is going to be the "person.vet.blah" and then return absolute_name which would be "person"
Fixing your code
As others have pointed out, you can't use absolute_name outside of the function in which it was defined. This is because you're when you return the variable from your function, all that is being returned is a pointer to the beginning of the array. Outside the function, the array itself no longer exists, so the pointer is invalid and you get a segfault if you try and dereference it.
You can get around this by using malloc. Don't forget to free the memory you have allocated when you are done using it.
By the way, as well as changing your loop to a while, I also fixed the check (you were checking machine_name[i] == '.', the opposite to what you wanted).
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char *separate_name(char *machine_name)
{
// allocate memory on the heap
char *absolute_name = malloc(strlen(machine_name)+1);
int i = 0;
while (i < strlen(machine_name) && machine_name[i] != '.') {
absolute_name[i] = machine_name[i];
++i;
}
absolute_name[i] = '\0';
return absolute_name;
}
int main()
{
char name1[] = "person.vet.blah";
char *first1 = separate_name(name1);
if (first1 != NULL) {
printf("%s\n", first1);
free(first1);
}
char name2[] = "word.friends.joe";
char *first2 = separate_name(name2);
if (first2 != NULL) {
printf("%s\n", first2);
free(first2);
}
return 0;
}
A better alternative
strtok is the perfect tool for the job:
#include <stdio.h>
#include <string.h>
char *separate_name(char *machine_name)
{
return strtok(machine_name, ".");
}
int main()
{
char name1[] = "person.vet.blah";
char *first1 = separate_name(name1);
if (first1 != NULL) printf("%s\n", first1);
char name2[] = "word.friends.joe";
char *first2 = separate_name(name2);
if (first2 != NULL) printf("%s\n", first2);
return 0;
}
As pointed out in the comments (thanks #John), strtok modifies the string that is passed to it (it replaces the delimiter . by the \0 null byte to mark the end of the string). This isn't a problem here but is something to be aware of.
Output using either program:
person
word
#include <stdio.h>
char *separate_name(const char *machine_name){
static char absolute_name[1000];
int i;
for (i =0; i < sizeof(absolute_name)-1 ; i++){
if(machine_name[i] == '.' || machine_name[i] == '\0'){
absolute_name[i] = '\0';
break;
} else {
absolute_name[i] = machine_name[i];
}
}
return absolute_name;
}
int main(void){
printf("%s\n", separate_name("person.vet.blah"));
printf("%s\n", separate_name("word.friends.joe"));
return 0;
}

Resources