I'm trying to parse a string around an arbitrary index. In my simplest test program I could come up with I have an input string I read the input into and then do memcpy to parse the string.
For testing this I am typing in "this text" as input. readInput is a function where I just have it calling getline(&input, &size, stdnin) and return the input pointer.
int main(){
char *input;
input = readInput();
int parseAround = 4;
char *token1;
char *token2;
memcpy(token1, inputBuffer, 4);
printf("token: %s\n", token1); //prints "this"
memcpy(token1, inputBuffer + (parseAround+1), 4);
//when changed to memcpy(token2,...); segfaults
printf("token: %s\n", token1); //prints "text"
free(input);
return 0;
}
However when I change the second memcpy to use token2 rather than token1, I get a segmentation fault. Why is this?
You most likely need to allocate memory for token1.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(){
char *input = NULL;
size_t len = 0;
ssize_t read;
/* Read in the line "Hello world" */
read = getline(&input, &len, stdin);
printf("Retrieved line of length %zu :\n", read);
printf("%s", input);
/* Allocate memory for both parts of the string */
char *token1 = malloc((read+1) * sizeof(char *));
char *token2 = malloc((read+1) * sizeof(char *));
memcpy(token1, input, 6);
printf("token: %s\n", token1); //prints "Hello"
memcpy(token2, (input+6), 5);
printf("token: %s\n", token2); //prints "world"
free(input);
return 0;
}
Read in the line, allocate memory for each string part, and then copy the part you want into your s
Related
I wanted to write a program in C that will accept a line of any length from stdin and display it or apply any function to that string. For this to work I will need a String (char []) with dynamic length.
This is how I did it:
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char **argv){
char *line;
line = malloc(10);
line[0] = '\0';
char *str = malloc(10);
fprintf(stdout, "Please enter your line:\n");
while(fgets(str, 10, stdin)){
//check for line break
if(str[strlen(str)-1] == '\n'){
str[strlen(str) - 1] = '\0';
strcat(line, str);
break;
}
strcat(line, str);
line = realloc(line, strlen(line) + 10);
str = realloc(str, strlen(str) + 10);
}
fprintf(stderr, "you entered %s\n", line);
//just for testing
/*
fprintf(stderr, "\n str= %s \n", str );
fprintf(stderr, "\n line= %s \n", line);
*/
free(line);
free(str);
exit(EXIT_SUCCESS);
}
However, this looks awful. I need two char arrays. In char *str I will write input from stdin and concatenate it to char *line. str will only hold up to 10Bytes of chars and because of that I need to concatenate everything to line.
Is there a cleaner way to save the output from stdin in this case and apply some function on it? Am I doing this wrong? Can it be done without malloc and realloc?
This an example. You need to add the malloc & realloc result checking (I did not for the sake of simplicity)
#include <stdio.h>
#include <stdlib.h>
#define CHUNK 32
char *readline(void)
{
size_t csize = CHUNK;
size_t cpos = 0;
char *str = malloc(CHUNK);
int ch;
while((ch = fgetc(stdin)) != '\n' && ch != '\r')
{
str[cpos++] = ch;
if(cpos == csize)
{
csize += CHUNK;
str = realloc(str, csize);
}
}
str[cpos] = 0;
return str;
}
int main()
{
printf("\n%s\n", readline());
return 0;
}
working example: https://onlinegdb.com/Sk9r4gOYV
You should also free the allocated memory when not needed anymore.
I am a bit confused about this little program:
When I run it, it loops till i = 999 and then gives "corrupted double linked list". In func1, printf is showing that str is like str2, but in main str is empty.
I observed that the program is working well if I do one of two things:
put in str2 a small string like "Hello".
comment the code related to database (sqlite3_open and sqlite3_close);
Thank you!
#include <stdio.h>
#include <string.h>
#include <sqlite3.h>
#include <stdlib.h>
sqlite3 *conn;
void func1 (char* str)
{
char str2[3000];
strcpy (str2, "dawNUkjhkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkdwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwaauhfuiahfsuehusehfseihfseifjhselfjslkejfklsejfksejksejfeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeejjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjUkjhkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkdwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwaauhfuiahfsuehusehfseihfseifjhselfjslkejfklsejfksejksejfeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeejjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjUkjhkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkdwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwaauhfuiahfsuehusehfseihfseifjhselfjslkejfklsejfksejksejfeeeeeeejjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjdawfa");
// strcpy (str2, "Hello\n");
str = (char*) realloc (str, sizeof (char) * (strlen (str2) * 2));
strcat (str, str2);
printf ("func1: %s\n", str);
}
int main ()
{
int dataBaseResult;
char* str = malloc (sizeof (char));
/* open database */
dataBaseResult = sqlite3_open ("magazin.db", &conn);
if (dataBaseResult != 0)
{
fprintf (stderr, "Problem %s\n", sqlite3_errmsg (conn));
}
else
{
printf ("Opened succesfully!\n");
}
for (int i = 0; i < 1000; i++)
{
printf ("main: %d\n", i);
strcpy (str, "");
func1 (str);
printf ("main: %s\n", str);
}
/* close database */
sqlite3_close (conn);
return 0;
}
Change func1 to correctly update the passed in pointer. Something like this:
void func1 (char **str)
{
char str2[3000];
char *tmp = NULL;
strcpy (str2, "...");
tmp = (char*) realloc (*str, sizeof (char) * (strlen (str2) * 2));
if (!tmp) {
*str = tmp;
}
strcat (*str, str2);
}
You are mallocing sizeof char which is 1 byte. malloc sizeof char * 3001
CODE HERE: http://ideone.com/AZnXFm
#include <stdio.h>
#include <stdlib.h>
#include<string.h>
int main()
{
char *buffer;
size_t bufsize = 32;
size_t characters;
buffer = (char *)malloc(bufsize * sizeof(char));
if( buffer == NULL)
{
perror("Unable to allocate buffer");
exit(1);
}
printf("Type something: ");
characters = getline(&buffer,&bufsize,stdin);
printf("%zu characters were read.\n",characters);
printf("You typed: %s",buffer);
char *end_str,*token2;
char *token = strtok_r(buffer,";",&end_str);
printf("token : %s \n", token);
int count =0,wordcnt=0;
while(token !=NULL)
{
char *end_token;
count++;
printf("outside count ------------------------%d\n", count);
strtok_r(token," ",&end_token);
while(token2!=NULL)
{
wordcnt++;
printf("insdie count %d\n",wordcnt);
printf("%s------------------- \n", token2);
token2 = strtok_r(NULL," ",&end_token);
}
token = strtok_r(NULL, ";",&end_str);
}
return(0);
}
Output is
Type something: rosie is; really good
22 characters were read.
You typed: rosie is; really good
token : rosie is
outside count ------------------------1
insdie count 1
AWAVA��AUATL�% -------------------
insdie count 2
is-------------------
outside count ------------------------2
A number of basic fixes are needed or have been applied in the code below:
Let getline() do the memory allocation.
Check that getline() read a line.
Free the memory allocated.
Set token2 with inner strtok_r() call.
Make variable names a bit more systematic.
Make characters into ssize_t to match the return from getline().
Print characters using %zd. This is marginally controversial; it prints the signed variant of size_t with the z-qualified signed decimal format string. It makes sense (to me at least and my compiler — GCC 6.2.0 on macOS Sierra), but I'm not sure where to find the confirmation that it is officially sanctioned by (the POSIX) standards.
Renaming variables for consistency.
Other minor cosmetic fixups (the print formatting could still be improved — quite a lot).
Leading to:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void)
{
char *buffer = 0;
size_t bufsize = 0;
ssize_t characters;
printf("Type something: ");
characters = getline(&buffer, &bufsize, stdin);
printf("%zd characters were read.\n", characters);
if (characters > 0)
{
printf("You typed: %s", buffer);
char *end_str1;
char *token1 = strtok_r(buffer, ";", &end_str1);
printf("token: %s \n", token1);
int count = 0, wordcnt = 0;
while (token1 != NULL)
{
char *end_str2;
count++;
printf("outside count ------------------------%d\n", count);
char *token2 = strtok_r(token1, " ", &end_str2);
while (token2 != NULL)
{
wordcnt++;
printf("inside count %d\n", wordcnt);
printf("%s------------------- \n", token2);
token2 = strtok_r(NULL, " ", &end_str2);
}
token1 = strtok_r(NULL, ";", &end_str1);
}
}
free(buffer);
return(0);
}
Example run:
Type something: rosie is; really good
22 characters were read.
You typed: rosie is; really good
token: rosie is
outside count ------------------------1
inside count 1
rosie-------------------
inside count 2
is-------------------
outside count ------------------------2
inside count 3
really-------------------
inside count 4
good
-------------------
I need to save the hex of a text to a string:
_____________________
Input: apple
Output: 6170706c65
_____________________
char * text = "apple";
char * hextext = convertToHex(text); // -> ?! I don't know how
printf("Hextext is %s\n", hextext); // -> Hextext is 6170706c65
and
char * hextext = 6170706c65;
char * text = convertToText(hextext);
printf("Text is %s\n", text);
Using Printf, its easy using %hx, but I need the values on the variables!
Can anybody help, please?!
Thanks.
My final code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void convertToHex(char* input, char** output)
{
char* ptr;
int i;
// Allocate memory for hex string
*output = malloc(2 * strlen(input) + 1);
// Initialize pointer to start of the output buffer
ptr = *output;
// Read each char in input. Use sprintf to append the 2 char hex value.
// Finally advance the pointer 2 places in the output buffer.
for(i=0; i<strlen(input); i++)
{
sprintf(ptr, "%x", input[i]);
ptr++; ptr++;
}
}
void convertHexToString(char* input, char** output)
{
char* ptr;
int c;
// Allocate memory for hex string
*output = malloc(2 * (strlen(input)/2)%2==0 ? (strlen(input)/2) + 1 : (strlen(input)/2));
// Initialize pointer to start of the output buffer
ptr = *output;
// Read two char in input. Use sprintf to append the char value.
// Finally advance the input place in the output buffer.
for (;input[0] && input[1] && sscanf(input, "%2x", &c); input += 2)
{
sprintf(ptr, "%c", c);
ptr++;
}
}
int main(void)
{
char* text = "apple";
char* hexkey;
char* strtext;
convertToHex(text, &hexkey);
printf("Input: %s\n", text);
printf("Output: %s\n", hexkey);
convertHexToString(hexkey, &strtext);
printf("\nInput2: %s\n", hexkey);
printf("Output2: %s\n", strtext);
free(hexkey);
free(strtext);
return 0;
}
Special thanks to Erik Nedwidek for help!
Here's what I was referring to:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void convertToHex(char* input, char** output) {
char* ptr;
int i;
// Allocate memory for hex string
*output = malloc(2 * strlen(input) + 1);
// Initialize pointer to start of the output buffer
ptr = *output;
// Read each char in input. Use sprintf to append the 2 char hex value.
// Finally advance the pointer 2 places in the output buffer.
for(i=0; i<strlen(input); i++) {
sprintf(ptr, "%x", input[i]);
ptr++; ptr++;
}
}
int main(void) {
char* text = "apple";
char* hex;
convertToHex(text, &hex);
printf("Input: %s\n", text);
printf("Output: %s\n", hex);
free(hex);
return 0;
}
The output is:
Input: apple
Output: 6170706c65
I want to append two strings. I used the following command:
new_str = strcat(str1, str2);
This command changes the value of str1. I want new_str to be the concatanation of str1 and str2 and at the same time str1 is not to be changed.
You need to allocate new space as well. Consider this code fragment:
char * new_str ;
if((new_str = malloc(strlen(str1)+strlen(str2)+1)) != NULL){
new_str[0] = '\0'; // ensures the memory is an empty string
strcat(new_str,str1);
strcat(new_str,str2);
} else {
fprintf(STDERR,"malloc failed!\n");
// exit?
}
You might want to consider strnlen(3) which is slightly safer.
Updated, see above. In some versions of the C runtime, the memory returned by malloc isn't initialized to 0. Setting the first byte of new_str to zero ensures that it looks like an empty string to strcat.
do the following:
strcat(new_str,str1);
strcat(new_str,str2);
Consider using the great but unknown open_memstream() function.
FILE *open_memstream(char **ptr, size_t *sizeloc);
Example of usage :
// open the stream
FILE *stream;
char *buf;
size_t len;
stream = open_memstream(&buf, &len);
// write what you want with fprintf() into the stream
fprintf(stream, "Hello");
fprintf(stream, " ");
fprintf(stream, "%s\n", "world");
// close the stream, the buffer is allocated and the size is set !
fclose(stream);
printf ("the result is '%s' (%d characters)\n", buf, len);
free(buf);
If you don't know in advance the length of what you want to append, this is convenient and safer than managing buffers yourself.
You'll have to strncpy str1 into new_string first then.
You could use asprintf to concatenate both into a new string:
char *new_str;
asprintf(&new_str,"%s%s",str1,str2);
I write a function support dynamic variable string append, like PHP str append: str + str + ... etc.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
int str_append(char **json, const char *format, ...)
{
char *str = NULL;
char *old_json = NULL, *new_json = NULL;
va_list arg_ptr;
va_start(arg_ptr, format);
vasprintf(&str, format, arg_ptr);
// save old json
asprintf(&old_json, "%s", (*json == NULL ? "" : *json));
// calloc new json memory
new_json = (char *)calloc(strlen(old_json) + strlen(str) + 1, sizeof(char));
strcat(new_json, old_json);
strcat(new_json, str);
if (*json) free(*json);
*json = new_json;
free(old_json);
free(str);
return 0;
}
int main(int argc, char *argv[])
{
char *json = NULL;
str_append(&json, "name: %d, %d, %d", 1, 2, 3);
str_append(&json, "sex: %s", "male");
str_append(&json, "end");
str_append(&json, "");
str_append(&json, "{\"ret\":true}");
int i;
for (i = 0; i < 10; i++) {
str_append(&json, "id-%d", i);
}
printf("%s\n", json);
if (json) free(json);
return 0;
}
I needed to append substrings to create an ssh command, I solved with sprintf (Visual Studio 2013)
char gStrSshCommand[SSH_COMMAND_MAX_LEN]; // declare ssh command string
strcpy(gStrSshCommand, ""); // empty string
void appendSshCommand(const char *substring) // append substring
{
sprintf(gStrSshCommand, "%s %s", gStrSshCommand, substring);
}
strcpy(str1+strlen(str1), str2);
man page of strcat says that arg1 and arg2 are appended to arg1.. and returns the pointer of s1. If you dont want disturb str1,str2 then you have write your own function.
char * my_strcat(const char * str1, const char * str2)
{
char * ret = malloc(strlen(str1)+strlen(str2));
if(ret!=NULL)
{
sprintf(ret, "%s%s", str1, str2);
return ret;
}
return NULL;
}
Hope this solves your purpose
You can try something like this:
strncpy(new_str, str1, strlen(str1));
strcat(new_str, str2);
More info on strncpy: http://www.cplusplus.com/reference/clibrary/cstring/strncpy/