Hi guys I got some problems with using a function with a reference to a string as argument. I read that you should use e double pointer for this, but I can't get it to work.
This is (partly) my code.
enum errCode { ERR_NONE = 0, ERR_EMPTY, ERR_FULL, ERR_MEM, ERR_INIT, ERR_COMMAND, ERR_UNDEFINED };
typedef enum errCode ErrCode;
typedef enum {
no = 0, add, del, src, show, exit
} Command;
int main(void) {
char stringval[50];
char stringval2[50];
ErrCode err;
Command currentCommand = no;
printf("Enter a command\n");
if (fgets(stringval, 50, stdin) != NULL) {
char *p;
if ((p = strchr(stringval, '\n')) != NULL)
*p = '\0';
}
ErrHandler(
extractCommand(¤tCommand, stringval, &stringval2)
);
printf("stringval 2 = %s.\n", stringval2);
return 0;
}
ErrCode extractCommand(Command *command, char *inputString, char **outputString) {
char *strTemp;
char *strTemp2;
//Get the first word of the string
strTemp = strtok(inputString, " ");
strTemp2 = strtok(NULL, " ");
*outputString = strTemp2;
//Check if it equals a command
if (strcmp(strTemp, "exit") == 0) {
*command = exit;
return ERR_NONE;
} else if (strcmp(strTemp, "add") == 0) {
*command = add;
return ERR_NONE;
} else if (strcmp(strTemp, "del") == 0) {
*command = del;
return ERR_NONE;
} else if (strcmp(strTemp, "src") == 0) {
*command = src;
return ERR_NONE;
} else if (strcmp(strTemp, "show") == 0) {
*command = show;
return ERR_NONE;
} else {
*command = no;
printf("%s", strTemp);
return ERR_COMMAND;
}
}
This is what my output looks like:
Enter a command
add this is a test
stringval 2 = z˜ˇøÀo‡èK‡èT¯ˇø.
I obviously want to have the second word of the inputted string, but I'm doing something wrong.
Thx for the help!
stringVal2 is not initialised and is never populated: that is reason junk is being printed. There is no need in this case to pass a char**, passing a char* will work. However, this:
outputString = strTemp2;
does not copy the content of strTemp2 to outputString: it makes outputString point to the same address as strTemp2: use strcpy().
A double pointer, char** for example, is commonly passed to a function when that function allocates a new buffer for the argument (which is not the case in the posted code):
char* buf = NULL;
my_alloc(&buf);
void my_alloc(char** p)
{
*p = malloc(10);
}
Related
I would like to copy the value stored in char *command to a char *command_copy, because I am performing tokenization on command but still would like to use the initial command (which is why I am creating a copy). The problem is that every time I try something, the whole program goes crazy and I just can't find where to start or what to do.
Here is my code:
int main(void)
{
init_ui();
hist_init(100);
char *command;
while (true) {
signal(SIGINT, SIG_IGN);
command = read_command();
if (command == NULL) {
break;
}
char *command_copy;
command_copy = (char *) malloc(1000);
memcpy(command_copy, command, sizeof(*command));
char *args[4096];
int tokens = 0;
char *next_tok = command;
char *curr_tok;
while((curr_tok = next_token(&next_tok, " \t\n\r")) != NULL) {
if(strncmp(curr_tok, "#", 1) == 0){
break;
}
args[tokens++] = curr_tok;
}
args[tokens] = NULL;
if(args[0] == NULL) {
continue;
}
hist_add(command);
int builtin_status = handle_builtins(tokens, args);
if(builtin_status == 0) {
continue;
}
pid_t child = fork();
if(child == -1){
perror("fork");
}
...
I would like the hist_add() function to take command_copy instead of command because command at that point in the code is only the first word of the whole initial command, and I would like hist_add() to have the whole (original) command.
read_command(void):
char *read_command(void)
{
if(scripting == true) {
ssize_t read_sz = getline(&line, &line_sz, stdin);
if(read_sz == -1){
perror("getline");
free(line);
return NULL;
}
line[read_sz - 1] = '\0';
return line;
}
else {
return readline(prompt_line());
}
}
To make a copy of a char* string - so long as that string is properly nul-terminated - you can use the strdup function. This, essentially, is a combination of malloc and strcpy.
So, you can use something like this:
while (looping) {
char* original = getstring();
char* copy = strdup(original);
// ...
// do whatever you want with "original" - "copy" is left alone!
//
free(copy); // When you're done, free the copy
}
The strdup call is equivalent to the following:
char* copy = malloc(strlen(original) + 1);
strcpy(copy, original);
I am writing a program that parses input from stdin and calls functions according to the input.
The inputs my program is supposed to handle are the following:
end //stops the program
report //prints a specific output
addent "ent_id"
delent "ent_id"
addrel "ent_id1" "ent_id2" "rel_id"
delrel "ent_id1" "ent_id2" "rel_id"
The functions called by the input are not relevant to my issue, but do note the all the arguments that are passed to the functions are between quotation marks.
Here's the code
int main() {
const char Comando[6][7] = { "addrel", "addent", "delrel", "delent", "report", "end" };
const char spazio[2] = " ";
const char newline[3] = "\n";
const char quote[2] = "\"";
char sample[100];
char *temp;
char *comandoIN;
char *argomento1;
char *dest;
char *rel;
RelHead = NULL;
init_array();
char *str = fgets(sample, 100, stdin);
for (;;) {
if (strncmp(sample, Comando[5], 3) == 0) {
return 0;
} else if (strncmp(sample, Comando[4], 6) == 0) {
report();
} else {
temp = strtok(sample, newline);
comandoIN = strtok(temp, spazio);
argomento1 = strtok(NULL, quote);
if (strncmp(Comando[1], comandoIN, 7) == 0) {
addent(argomento1);
} else if (strncmp(Comando[3], comandoIN, 7) == 0) {
delent(argomento1);
} else {
temp = strtok(NULL, quote);
dest = strtok(NULL, quote);
temp = strtok(NULL, quote);
rel = strtok(NULL, quote);
if (strncmp(Comando[0], comandoIN, 7) == 0) {
addrel(argomento1, dest, rel);
} else if (strncmp(Comando[2], comandoIN, 7) == 0) {
delrel(argomento1, dest, rel);
}
}
}
char *str = fgets(sample, 69, stdin);
}
return 0;
}
The incorrect behavior is cause by the following input:
addrel "The_Ruler_of_the_Universe" "The_Lajestic_Vantrashell_of_Lob" "knows"
which causes the last two calls of strtok to return NULL instead of " " (whitespace) and "knows" respectively (without quotation marks).
Furthermore, if this is the first input given to the program, it behaves correctly, and if it's the last, the following cycle will put "knows" in the "comandoIN" variable. This is the only input I've found so far that causes this issue, and I think it has something to do with removing the newline character with the first call of strtok.
This is an assignment for uni, so we have several inputs to test the program, and my program passes the first 4 of these (the tests are about 200 inputs each), so I don't really understand what's causing the bug. Any ideas?
The problem here is that the input:
addrel "The_Ruler_of_the_Universe" "The_Lajestic_Vantrashell_of_Lob" "knows"
is 77 bytes long (76 characters plus terminating NULL).
At the end of your loop you have:
char *str = fgets(sample, 69, stdin);
where your state that your buffer is 69 long.
Why does it behave correctly if it is the first input?
Before the for loop you have:
char *str = fgets(sample, 100, stdin);
for(;;)
...
Here you use a size of 100, so it works if you first use the above input directly after starting the program.
Using strtok for parsing the command line with different sets of separators is confusing and error prone. It would be simpler to parse the command line with a simple loop and handle spaces and quotes explicitly, then dispatch on the first word.
Here is a more systematic approach:
#include <stdio.h>
char *getarg(char **pp) {
char *p = *pp;
char *arg = NULL;
while (*p == ' ')
p++;
if (*p == '\0' || *p == '\n')
return arg;
if (*p == '"') {
arg = ++p;
while (*p != '\0' && *p != '"')
p++;
if (*p == '"')
*p++ = '\0';
} else {
arg = p++;
while (*p != '\0' && *p != ' ' && *p != '\n')
p++;
if (*p != '\0')
*p++ = '\0';
}
*pp = p;
return arg;
}
int main() {
char sample[100];
char *cmd, *arg1, *arg2, *arg3;
RelHead = NULL;
init_array();
while (fgets(sample, sizeof sample, stdin)) {
char *p = sample;
cmd = getarg(&p);
arg1 = getarg(&p);
arg2 = getarg(&p);
arg3 = getarg(&p);
if (cmd == NULL) { // empty line
continue;
} else
if (!strcmp(cmd, "end")) {
break;
} else
if (!strcmp(cmd, "report")) {
report();
} else
if (!strcmp(cmd, "addent")) {
addent(arg1);
} else
if (!strcmp(cmd, "delent")) {
delent(arg1);
} else
if (!strcmp(cmd, "addrel")) {
addrel(arg1, arg2, arg3);
} else
if (!strcmp(cmd, "delrel")) {
delrel(arg1, arg2, arg3);
} else {
printf("invalid command\n");
}
}
return 0;
}
I am parsing a file in C, line by line. Here is an exemple of what I am trying to do :
I have a line for example :
word word word WORDTOFIND: word1 word2 word word
What I want to do is : When I find the word WORDTOFIND, get the two next words (word1 and word2 in this case) of the line. Is there an easy way to do that in C ? I know about the strstr function, but I don't find a way to get the next two words word1 and word2 after I found the good one.
One approach would be this:
int main(void)
{
char *str = "rated rat cat bat hat";
char *key = "rat ";
char *pointer = NULL;
char nwords = 2;
if ((pointer = strstr(str, key)) != NULL)
{
while (*pointer != ' ') pointer++;
while (nwords >= 0)
{
printf("%c", *pointer);
if (*pointer == ' ') {
nwords--;
} else if (*pointer == '\0') {
exit(0);
}
pointer++;
}
}
}
You can try an aproach like this, using strtok to parse the words at every space. This code also uses malloc and realloc to allocate space for an array of strings, and grows it when needed.
The code looks like this:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#define MAXCHAR 100
void exit_if_null(void *ptr, const char *msg);
char *stripped_word(char *word);
int
main(int argc, char const *argv[]) {
FILE *filename;
char line[MAXCHAR];
char *word, *newword;
char **allwords;
int init_size = 8, count = 0, i;
const char *key = "WORDTOFIND";
filename = fopen("files.txt", "r");
if (filename == NULL) {
fprintf(stderr, "%s\n", "Error reading file!");
exit(EXIT_FAILURE);
}
allwords = malloc(init_size * sizeof(*allwords));
exit_if_null(allwords, "Initial Allocation");
while (fgets(line, MAXCHAR, filename) != NULL) {
word = strtok(line, " \n");
while (word != NULL) {
if (count == init_size) {
init_size *= 2;
allwords = realloc(allwords, init_size * sizeof(*allwords));
}
allwords[count] = malloc(strlen(word)+1);
exit_if_null(allwords[count], "Initial Allocation");
newword = stripped_word(word);
strcpy(allwords[count], newword);
count++;
word = strtok(NULL, " \n");
free(newword);
}
}
for (i = 0; i < count; i++) {
if (strcmp(key, allwords[i]) == 0) {
printf("Next two words:\n");
printf("%s\n", allwords[i+1]);
printf("%s\n", allwords[i+2]);
}
free(allwords[i]);
allwords[i] = NULL;
}
free(allwords);
allwords = NULL;
return 0;
}
void
exit_if_null(void *ptr, const char *msg) {
if (!ptr) {
printf("Unexpected null pointer: %s\n", msg);
exit(EXIT_FAILURE);
}
}
char
*stripped_word(char *word) {
int i, pos = 0;
char *result;
result = malloc(strlen(word)+1);
exit_if_null(result, "Initial Allocation");
for (i = 0; word[i] != '\0'; i++) {
if (isalpha(word[i]) || isdigit(word[i])) {
result[pos++] = word[i];
}
}
result[pos] = '\0';
return result;
}
I have a problem in my C program. This is the String Search program. The problem is when I type the String aabaaacaamaad, the result comes NULL when I search for ab in it but it should not as ab is there in aabaaacaamaad. The same result also comes with am and ad which is right but why does it come with aabaaacaamaad? Code:
char* MyStrstr(char* pszSearchString, char* pszSearchWord);
int main(int argc, char* argv[])
{
char szTemp1[20] = {0};
char szTemp2[10] = {0};
char * pszTemp1 = NULL;
strcpy(szTemp1, "aabaaacaamaad");
strcpy(szTemp2, "aa");
pszTemp1 = MyStrstr(szTemp1, szTemp2);
printf("%s", pszTemp1);
getch();
return 0;
}
char* MyStrstr(char* pszSearchString, char* pszSearchWord)
{
int nFcount = 0;
int nScount = 0;
int nSearchLen = 0;
int nIndex = 0;
char* pszDelString = NULL;
if(pszSearchString == NULL || pszSearchWord == NULL) {
return NULL;
}
while(pszSearchWord[nSearchLen] != '\0') {
nSearchLen++;
}
if(nSearchLen <= 0){
return pszSearchString;
}
for(nFcount = 0; pszSearchString[nFcount] != '\0'; nFcount++) {
if(pszSearchString[nFcount] == pszSearchWord[nScount]) {
nScount++;
} else {
nScount = 0;
}
if(nScount == nSearchLen) {
nIndex = (nFcount - nScount) + 1;
pszDelString = pszSearchString + nIndex;
return pszDelString;
}
}
return NULL;
}
I see what your code is trying to do, you want to avoid a loop in a loop but however you're missing one thing. When a match fails you're not going back but still moving forward in pszSearchString while you should not. The result of this flaw is that with incomplete matches you skip characters. That's the reason why the strstr function originally uses a loop in a loop so for every character in pszSearchString there is an new loop to match with pszSearchWord. Here the original strstr.c file from BSD/Darwin:
char * strstr(const char *in, const char *str)
{
char c;
size_t len;
c = *str++;
if (!c)
return (char *) in; // Trivial empty string case
len = strlen(str);
do {
char sc;
do {
sc = *in++;
if (!sc)
return (char *) 0;
} while (sc != c);
} while (strncmp(in, str, len) != 0);
return (char *) (in - 1);
}
I have such a structure:
typedef struct kodProgramu {
char* etykieta;
char* instrukcja;
char* operand;
struct kodProgramu *nast;
} kodPrg;
This code is for adding new element:
void pobierzKodStdin(kodPrg *kod, char *wynik, char *linia, int flagaEtyk)
{
wynik = fgets(linia, 80, stdin);
while(wynik != NULL)
{
kodPrg *wsk, *nowy;
wsk = kod;
while(wsk->nast != NULL)
wsk = wsk->nast;
if(linia[0] == ' ')
flagaEtyk = 1;
nowy = (kodPrg*)malloc(sizeof(kodPrg));
int licznik = 0;
char *pch;
pch = strtok(linia, ":# ");
while(pch != NULL)
{
if(flagaEtyk == 0)
{
if(licznik == 0)
nowy->etykieta = pch;
else if(licznik == 1)
nowy->instrukcja = pch;
else if(licznik == 2)
nowy->operand = pch;
}
if(flagaEtyk == 1)
{
if(licznik == 0)
nowy->instrukcja = pch;
else if(licznik == 1)
nowy->operand = pch;
}
licznik++;
pch = strtok(NULL, ":# ");
}
nowy->nast = NULL;
wsk->nast = nowy;
flagaEtyk = 0;
wynik = fgets(linia, 80, stdin);
}
}
This function print this structure to the console:
void wypiszKod(kodPrg *kod)
{
kodPrg *wsk = kod;
while(wsk != NULL)
{
printf("%s %s %s\n", wsk->etykieta, wsk->instrukcja, wsk->operand);
wsk = wsk->nast;
}
}
This is my main function:
int main()
{
char linia[80], *wynik;
char *wsk = malloc(sizeof(char));
int flagaEtyk = 0;
//tasmaWejsc *wejscie = (tasmaWejsc*)malloc(sizeof(tasmaWejsc));
//tasmaWyjsc *wyjscie = (tasmaWyjsc*)malloc(sizeof(tasmaWyjsc));
//wyjscie->wartosc = 0;
//wyjscie->nast = NULL;
kodPrg *kod = (kodPrg*)malloc(sizeof(kodPrg));
kod->etykieta = " ";
kod->instrukcja = " ";
kod->operand = " ";
kod->nast = NULL;
int liczba;
//wprowadzWejscie(wynik, linia, wejscie);
//wypiszWejscie(wejscie);
//system("cls");
pobierzKodStdin(kod, wynik, linia, flagaEtyk);
wypiszKod(kod);
return 0;
}
Now, when I enter one line like : test test test
It's working good and print test test test in console.
But when I enter more lines, for example:
test test test
xxxx xxxx xxxx
The program is printing:
xxxx xxxx xxxx
xxxx xxxx xxxx
It's like the second line replace the first one.
I don't know why, when I have a struct with int instead of char * it's working good. Next element are added and it' printing good, but when char * it's working as I described above.
How to add new elemnt to the list when I have struct with char *?
I think you should realize that strtok works on a static buffer
So when you write like this
pch = strtok(linia, ":# ");
while(pch != NULL)
{
if(flagaEtyk == 0)
{
if(licznik == 0)
nowy->etykieta = pch;
you are assigning the pointer in your shiny heap element to a string that will disappear by the next line (linia).
wynik = fgets(linia, 80, stdin);
what you need to do is to make a copy of the string, this can be done using strdup()
nowy->etykieta = strdup(pch);
Every string in your linked list is mapped to portions of linia[80], which is overwritten at each line access.
Some strdup() calls should solve your issue.