Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 6 years ago.
Improve this question
Im making a lexer and I'm trouble copying a string from my file buffer to the string property of the constructor. Here is the code i'm using to copy a string from the buffer.
static token_t* lexer_str(lexer_t* lexer) {
size_t str_len = 0;
while (true) {
if (lexer->len < 1) {
error_new(lexer->errors, lexer->len, lexer->pos, "Unterminated string.");
return NULL;
} else if (lexer_look(lexer, 0) == '\"') {
lexer_adv(lexer, 1);
break;
} else {
lexer_adv(lexer, 1);
str_len++;
}
}
char* string = malloc(str_len);
for (size_t idx = 0; idx < str_len; idx++)
string[idx] = lexer->src[lexer->ptr - str_len + idx];
token_t* token = token_new(lexer, _str);
token->string = string;
return token;
}
And here is the buffer.
"la la la" "me me me"
and here is the output, the string is coming out as "²²²²\"
Type:0 {
Line: 1
Pos: 0
Number: 10715872
Real: 10715872
String: ²²²²\
}
Why is this happening? Is it just me reading memory from the wrong place. Any help for how I could correctly copy the string into the token would be appricated.
First char* string = malloc(str_len); is too short, and your string is not null terminated after the copy (you copy a buffer given offset and len, the buffer does not contain an ending null char)
change to:
char* string = malloc(str_len+1); // 1 byte more
for (size_t idx = 0; idx < str_len; idx++)
string[idx] = lexer->src[lexer->ptr - str_len + idx];
string[str_len] = '\0'; // don't forget to null-terminate
If the source is, say, empty, then you have a non-null terminated string in string
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 1 year ago.
Improve this question
Safe input is harder than I thought. I looked around and found this, but it is from 2011 and things might have changed since then.
I'm looking for something that can handle string input and single character input. For example:
Hello, what's your name?
My name is: _
Are you sure?
[Y] Yes, hello
[N] No, goodbye
_
Here is the way I'm doing it right now:
char input[16];
fgets(input, 16, stdin);
char input = getchar();
My problem has always been that the user may input arbitrarily long input or invalid input. How can I read input safely and ensure future inputs won't get borked?
Looking for solutions that work in C and across Linux / Windows.
Thank you for your time.
You are able to read infinite standard input safely. You can just use a continuously reallocating buffer.
#include <stdio.h>
#include <stdlib.h>
char* get_line(size_t* length) {
size_t len = 0;
size_t cap = 4;
char* buffer = malloc(cap);
if (buffer == NULL) {
fprintf(stderr, "Virtual memory exhausted\n");
return NULL;
}
char current;
while ((current = getchar()) != '\n') {
if (len + 1 > cap) {
cap *= 2;
buffer = realloc(buffer, cap);
}
buffer[len++] = current;
}
// One last time for NUL terminator
if (len + 1 > cap) {
cap *= 2;
buffer = realloc(buffer, cap);
}
buffer[len] = 0;
if (length) *length = len;
return buffer;
}
This function will read stdin char-by-char and add it to a string which is returned. Optionally you can ask for its length. Don't forget to free.
int main() {
char* line = get_line(NULL);
printf("You entered: %s\n", line);
free(line);
}
NOTE: This code is meant to be of little verbosity so some checks were omitted. In production code checking realloc and using int for getchar() to test for EOF is necessary.
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.
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
How can I read multiple lines (approximately 5000 lines) from a text file and store all of them in a single string array?
i already have some of the code running smooth, but it doesn't work the way its supposed to. I only get the last line of the file stored in the array.
int main(){
int n;
char line[401];
char string[10000];
fr = fopen ("fila1b.txt", "rt");
while(fgets(line, 400, fr) != NULL){
strcat(string, line);
}
fclose(fr);
printf("%s\n", string );
}
EDIT: I updated the code with some changes. Now i'm using the strcat function to insert the contents of the line got by fgets to the original string array. It is working, apparently. But when i print the 'string', it only prints the first 300 lines and then it gives me Segmentation fault.
The usual way is to just slurp all the characters with read or fread:
#define MIN_CHUNK_SIZE (1024)
char *read_file(FILE *f) {
size_t n_read_total = 0;
size_t buf_size = MIN_CHUNK_SIZE + 1; // Allow space for nul terminator.
char *buf = safe_malloc(buf_size);
size_t n_avail;
do {
n_avail = buf_size - n_read_total - 1;
if (n_avail < MIN_CHUNK_SIZE) {
// Double the buffer size.
n_avail += buf_size;
buf_size += buf_size;
buf = safe_realloc(buf, buf_size);
}
size_t n_read = fread(buf + n_read_total, 1, n_avail, f);
n_read_total += n_read;
} while (n_read == n_avail);
buf[n_read_total] = '\0';
return safe_realloc(buf, n_read_total + 1);
}
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 8 years ago.
Improve this question
I'm trying to split up a string (typed in by the user at run time) into words (separated by spaces), and put each word into a different slot into an array. So, for example, if I took the string "hello world", array[0] would contain "hello" and array[1] would contain "world". And the last slot (in this case array[2]) would contain NULL. Here's what I have so far, which doesn't seem to be working properly. Any help would be appreciated. (By the way, this is part of a program which will call execvp(argv[0],argv); )
char input[100];
char* argv[20];
char* token;
scanf("%s", input);
//get the first token
token = strtok(input, " ");
int i=0;
//walk through other tokens
while( token != NULL ) {
argv[i] = token;
i++;
token = strtok(NULL, " ");
}
argv[i] = NULL; //argv ends with NULL
You need to allocate memory for each argv[i] and copy the current token to argv[i]:
token = strtok(input, " ");
int i=0;
//walk through other tokens
while( token != NULL ) {
argv[i] = malloc(strlen(token) + 1);
strncpy(argv[i], token, strlen(token));
//argv[i] = token;
i++;
token = strtok(NULL, " ");
}
argv[i] = NULL; //argv ends with NULL
I have created an example of what I think you want. I have used one malloc(3) for the whole
line of strings and another for the array of pointers you will get from the function.
Also, the second parameter of strtok(3) is passed to give more flexibility (the shell normally uses the contents of IFS environment variable to separate arguments so you can use the same algorithm as the shell does) I think you should use " \n\t" at least. It has a main() test function, so it's complete for your purpose.
#include <assert.h> /* man assert(3) */
#include <stdlib.h> /* malloc lives here */
#include <string.h> /* strtok, strdup lives here */
#include <stdio.h> /* printf lives here */
char **split(const char *str, const char *delim)
{
char *aux;
char *p;
char **res;
char *argv[200]; /* place for 200 words. */
int n = 0, i;
assert(aux = strdup(str));
for (p = strtok(aux, delim); p; p = strtok(NULL, delim))
argv[n++] = p;
argv[n++] = NULL;
/* i'll put de strdup()ed string one place past the NULL,
* so you can free(3), once finished */
argv[n++] = aux;
/* now, we need to copy the array, so we can use it outside
* this function. */
assert(res = calloc(n, sizeof (char *)));
for (i = 0; i < n; i++)
res[i] = argv[i];
return res;
} /* split */
int main()
{
char **argv =
split("Put each word of a string into array in C", " ");
int i;
for (i = 0; argv[i]; i++)
printf("[%s]", argv[i]);
puts(""); /* to end with a newline */
free(argv[i+1]);
free(argv);
} /* main */
The sample code just outputs:
$ pru
[Put][each][word][of][a][string][into][array][in][C]
I think I just figured out my problem: I need to use gets() instead of scanf(), because scanf() only gets the first word, up until a space, while I want to be able to get a string containing multiple words separated by spaces.