Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 3 years ago.
Improve this question
I'm attempting to replace '%7C' with a '|' in C but i'm getting a multi-character character constant warning. I was wondering if it was possible to do this and if so how? I was attempting using the code below but it gave this warning.
Parse.c
char *parse(char *command){
char * newCommand = (char *)malloc(sizeof(char)*35);
newCommand = strtok(command, " ");
newCommand = strtok(NULL, "/run?command= ");
for(int i = 0; i<strlen(newCommand); i++){
if(newCommand[i] == '+')
{
newCommand[i] = ' ';
}
if(newCommand[i] == '%7C')
{
newCommand[i] = '|';
}
}
return newCommand;
}
Multi-character constants are not portable and should generally be avoided. Your code comes under the 'general' category.
Part of the solution to your problem is to do a string comparison (with strncmp):
if (strncmp(&newCommand[i], "%7C", 3) == 0)
{
newCommand[i] = '|';
}
However, you also need to remove the 7C. That requires more surgery on the loop:
int tgt = 0;
int len = strlen(newCommand);
for (int src = 0; src < len; src++)
{
if (newCommand[src] == '+')
{
newCommand[tgt++] = ' ';
}
else if (strncmp(newCommand[i], "%7C", 3) == 0)
{
newCommand[tgt++] = '|';
src += 2;
}
else
newCommand[tgt++] = newCommand[src];
}
newCommand[tgt] = '\0';
This maintains two indexes into the newCommand array, one from which you're reading (src) and one to which you're writing (tgt — dst would be an alternative name). The src += 2; skips over the 7C after replacing % with |.
Uncompiled code!
Also, in your function you have:
char *newCommand = (char *)malloc(sizeof(char)*35);
newCommand = strtok(command, " ");
This immediately leaks the allocated memory. Maybe you need to use strdup() or:
char *newCommand = malloc(strlen(command) + 1);
if (newCommand == NULL) …report error and bail out…
strcpy(newCommand, command);
And the next line:
newCommand = strtok(NULL, "/run?command= ");
splits on any sequence of any of the characters in the constant string; it does not look for that string. If you want to look for the string, then you need strstr() instead, and you need to run strtok() first, perhaps, to get the right starting point (maybe newCommand = strtok(NULL, ""), then char *end = strstr(newCommand, "/run?command= "); — and check for null pointers returned.
With the revised allocation, you need a new symbol to record the pointers returned by strtok() — such as char *token;.
All in all, there's a lot of work needed on your code.
Related
Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
This question does not appear to be about programming within the scope defined in the help center.
Closed 9 months ago.
Improve this question
Could you please provide me some code or solution how to split the below string in C programming
Sample string :
SMABCDEFGHIJK,887276617459,5,552612260849779,552612260840646,552612260843632,552612260843525,552612260846817
Output needed :
552612260849779,552612260840646,552612260843632,552612260843525,552612260846817
Basically for the input string we would need to Ignore first 3 positions and want rest of the string in different variable.
The positions to ignore and delimiter values will get the from the database table label.
So, If someone help me to give the logic that would be very helpful
In your case, you do not need to split the string. Simply ignore everything before the n-th occurrence of the delimiter.
char *ignoreFisrstN(const char *str, int delim, size_t ignoreCount)
{
char *result = NULL;
while(ignoreCount--)
{
if((str = strchr(str, delim))) str++;
else break;
}
if(str)
{
result = malloc(strlen(str) + 1);
if(result) strcpy(result, str);
}
return result;
}
int main(void)
{
char *s = "SMABCDEFGHIJK,887276617459,5,552612260849779,552612260840646,552612260843632,552612260843525,552612260846817";
for(size_t i = 0; i < 10; i++)
{
char *r = ignoreFisrstN(s, ',', i);
printf("%zu: `%s`\n", i, r ? r : "NULL");
free(r);
}
}
https://godbolt.org/z/xWe74sY46
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 4 years ago.
Improve this question
I'm trying to find the best way to compare multiple strings in C.
Currently, I'm using strcmp(); function, but it's turning out to be too many if
statements. I was also using ternary operator but unfortunately for me, it doesn't help.
Is there any better solution?
Here is example code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
char command[] = "First Second Third";
char * del = " ";
char * token;
char * strings[3];
int n = 0;
token = strtok(command, del);
while (token != NULL){
strings[n] = token;
token = strtok(NULL, del);
n++;
}
// Now, strings[0] = "First", strings[1] = "Second", and strings[2] = "Third"
// Only examine strings[1] and strings[2] after we know strings[0] = "First".
if (strcmp("First", strings[0]) == 0){
//do something
if (strcmp("Second", strings[1]) == 0){
//do something
if (strcmp("Third", strings[2]) == 0){
//do something
printf("CORRECT");
//do something
}
}
}
return 0;
}
OP's code has some problems
while (token != NULL) has no limit to 3 loops. Code may attempt strings[3] = token;
// while (token != NULL){
while (n < 3 && token != NULL){
Code uses strings[0], strings[1], strings[2] without first insuring that many tokens were parsed.
// strcmp("First", strings[0]) == 0
(n > 0 && strcmp("First", strings[0]) == 0)
Code saves a pointer to the original string. Once strtok() is call again, the prior token can be lost/changed.
The "best" way involves hashing the key and targets, yet that is a lot to explain here.
Alternative: With such a simple match needed as in OP's example, code could use "%n" to record the offset of the scan.
int n1 = 0, n2 = 0, n3 = 0;
sscanf(command, "First %n Second %n Third %n", &n1, &n2, &n3);
if (n1) { // n1 is non-zero if scan matched "First"
//do something
if (n2) { // n2 is non-zero if scan matched "First Second"
//do something
if (n3) {
//do something
printf("CORRECT");
//do something
}
}
}
It looks like your if statements should be using strcmp() instead of the posted strtok(). Also, I think you are looking for something more like if ... else if ... else if ..., rather than nested if's.
Depending on the real program you're writing (vs. posted), you could also use a switch() based on the first character in the string to compare. It amounts to a crude hashing function. (you may want to learn more about hashing to adapt what you have to what you want).
EDIT:
Maybe this is what you're getting at:
.
.
.
if (strcmp(strings[0], "cmdA") == 0)
processCmdA(strings[1], strings[2]);
else
if (strcmp(strings[0], "cmdB") == 0)
processCmdB(strings[1], strings[2]);
else
if (strcmp(strings[0], "cmdC") == 0)
processCmdC(strings[1], strings[2]);
.
.
.
void processCmdA(char* optionA, char* inputFileName)
{
if (strcmp(optionA, "parse") == 0)
parseFile(inputFileName);
else
if (strcmp(optionA, "cksum") == 0)
computeCheckSum(inputFileName);
else
.
.
.
}
void parseFile(char* inputFileName)
{
// do parse stuff
}
.
.
.
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 6 years ago.
Improve this question
i already have this code in C language, is a string of 15 data delimited by commas the code split the string by comma and store every data in a single variable called array[], the issue is that i have the last data comma if after the last comma there are no data then the variable x15 = 0, but if there are a value after the last , then convert that value to a int. i print the value of the array[15] to verify and this is null, so i out a condition for that but do not work, the program just break after compiling.
char buf[] ="¶bL0 L3,01,+08590323,-079343001,010215,00000000000000,-tN,000,012689997,001219456,000,7FF2,C07F,0,4,";
printf("\n \n string=[%s]\n\n", buf);
int i = 0;
int u;
char *p = strtok (buf, ",");
char *array[16];
char *y15;
while (p != NULL)
{
array[i++] = p;
p = strtok (NULL, ",");
}
for (i = 0; i <16; ++i){
if(array[15] == NULL){
wbt.x15=0;
}else{
wbt.x15=atoi(array[15]);
}
//printf("data: [%s]\n", array[i]);
}
You are using an uninitialized array element, which is cause for undefined behavior.
You have:
char *array[16];
The elements of the array are uninitialized. And then, you proceed to use:
if(array[15] == NULL){
wbt.x15=0;
}else{
wbt.x15=atoi(array[15]);
}
It's not clear why you have that check for every iteration of the loop but that's another problem. The problem with the posted code is that array[15] is not initialized. Using that value is a problem.
Make sure you initialize array properly. Use:
char *array[16] = {0};
Also, I think your for loop needs to be something like:
for (i = 0; i <16; ++i)
{
int x = 0;
if(array[i] != NULL)
{
x = atoi(array[i]);
}
// Now use x.
}
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 6 years ago.
Improve this question
I'm having some issues with this code and would mind to get a little help. This function reads from file to the dynamically allocated memory
Thanks #JonathanLeffler for help - function indent works perfectly! But one more issue appeared: with function read_file, that reads from file to char array, that is later passed to the indent.
=========================================================================
//--------------- read_file valgrind validations --------------------
==396== 144 bytes in 1 blocks are definitely lost in loss record 62 of 66
==396== at 0x4C2AD10: calloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==396== by 0x401AC1: read_file (polisher.c:24)
==396== by 0x4025CE: test_indent (test_source.c:174)
==396== by 0x406BC7: srunner_run (in /tmc/test/test)
==396== by 0x402C67: tmc_run_tests (tmc-check.c:134)
==396== by 0x402902: main (test_source.c:235)
==396==
=====================================================
char *read_file(const char *filename)
{
FILE *f = fopen(filename, "r");
if(!f)
return NULL;
int n = 0, c = 0;
char *a = NULL;
c = fgetc(f);
while(c != EOF)
{
n++;
c = fgetc(f);
}
freopen(filename, "r", f);
a = calloc(n + 1, sizeof(char));
c = fgetc(f);
n = 0;
while(c != EOF)
{
a[n] = c;
n++;
c = fgetc(f);
}
a[n] = '\0';
fclose(f);
return a;
}
================================================================
START_TEST(test_indent)
{
char *str = read_file("testifile.c");
if (!str) str = read_file("test/testifile.c");
if (!str) {
fail("[M6.01.c] read_file(\"testifile.c\") returned NULL");
}
char *res = indent(str, " ");
if (!res) {
free(str);
free(res);
fail("[M6.01.c] indent(\"testifile.c\") returned NULL");
}
char buf[OUTPUTLEN];
if (mycompare_new(res, ref61c, buf, OUTPUTLEN)) {
free(res);
free(str);
fail("[M6.01.c] Invalid string from indent(\"testifile.c\"): %s", buf);
}
free(str);
free(res);
test_complete();
}
END_TEST
Your basic problem is that the code for adding a single character to the output buffer doesn't check whether there's space for the extra character, and there might not be. You can tickle the bug quicker by using a longer indent (e.g. " /* Look Ma! */ ", which is 16 characters).
Where you currently have:
continue;
}
dest[dest_offset++] = c;
input++;
}
the brute force and carelessness solution adds:
continue;
}
if (dest_offset >= dest_len)
{
printf("XX: DO = %zu, DL = %zu, PL = %zu, LV = %zu\n", dest_offset, dest_len, pad_len, pad_level);
putchar('#');fflush(0);
char *ptr = realloc(dest, dest_len * 2);
if(!ptr)
{
free(dest);
return NULL;
}
dest_len *= 2;
dest = ptr;
}
putchar('.');fflush(0);
dest[dest_offset++] = c;
input++;
}
Oh, and I left some of the debug code I ended up using on display. I added quite a lot of vaguely similar printing code. An assertion at the top of the loop helped, too: assert(dest_offset <= dest_len);. When that went firing, things became clearer (but it took me a while to find out why it was firing). I also butchered the test in the newline handling code to:
if (dest_offset >= dest_len || (pad_len * pad_level + 1) >= (dest_len - dest_offset))
{
printf("YY: DO = %zu, DL = %zu, PL = %zu, LV = %zu\n", dest_offset, dest_len, pad_len, pad_level);
putchar('#');fflush(0);
char *ptr = realloc(dest, dest_len * 2);
if(!ptr)
{
free(dest);
return NULL;
}
dest_len *= 2;
dest = ptr;
}
but that realloc() never fired, which was one of the surprises.
I think you need a function to add one character to your output buffer, and you need to wrap up the output buffer control into a structure (struct Buffer { char *buffer; size_t maxlen; size_t curlen; } or thereabouts), and you have that one function deal with (re)allocating space as needed. That will avoid the glaring repeat of the 'brute force and carelessness' solution. You can make it a static inline function if you like — the compiler might avoid some overhead that way without compromising the readability of your code. There's also a nasty repeat with the two loops to add multiples of the indent to the buffer. That would be best treated with another function, of course — but it would be different from the 'add one char' in that you can sensibly check for enough space and do the reallocation once. Or write the function to take a length and pointer to a buffer that is not null terminated (so a single character has length 1 and the padding string has length pad_len) and a single function can do the whole lot — probably a better solution. I'd still package the controls into a structure and let the compiler optimize.
Test main():
int main(void)
{
char data[] = "#include <stdio.h>\nint main(void)\n{\nputs(\"Hello World!\\n\");\nreturn 0;\n}\n";
printf("Before: [[%s]]\n", data);
fflush(0);
char *reformatted = indent(data, " /* Look Ma! */ ");
printf("Indent: -complete-\n");
fflush(0);
printf("Source: [[%s]]\n", data);
fflush(0);
printf("Target: [[%s]]\n", reformatted);
free(reformatted);
return 0;
}
Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 6 years ago.
Improve this question
I am new to C
I am trying to parse the string by "spaces" and "commas", string that *ch pointing to, but I am getting the first element only. Not sure what I am doing wrong, and I have wasted my whole day already on this, but still couldn't figure out.
#include <stdio.h>
#include <string.h>
int main(){
char *ch = "This is a string, and fyunck you.";
char cmd[100], *temp;
int i = 0, size_ch = strlen(ch), count = 0;
/* as strtok only support string array */
for (i = 0; i < size_ch; i++){
if (ch[i] != ','){
cmd[count] = ch[i];
count++;
}
}
cmd[count] = '\0';
printf("cmd: %s\n", cmd);
ch = strtok(cmd, " ");
printf("ch: %s\n", ch);
while ( (ch = strtok(NULL, " ")) != NULL)
printf("%s\n", cmd);
}
Output
cmd: This is a string and fyunck you
ch: This
This
This
This
This
This
This
whereas, the output should be
Desire Output
cmd: This is a string and fyunck you
ch: This
is
a
string
and
fyunck
you
Note: I am not allowed to use external libraries.
P.S I am trying to replicate this code, Code
You're just printing the wrong variable in the last line.
Change
printf("%s\n", cmd);
to
printf("%s\n", ch);
and it should be fine.
Note this:
while ((ch = strtok(NULL, " ")) != NULL)
printf("%s\n", cmd);
You are updating ch, and outputting cmd, which remains unchanged.
To fix this, simply change it to:
while ((ch = strtok(NULL, " ")) != NULL)
printf("%s\n", ch);