The first if condition leads to a segmentation fault. I can't really comprehend why, since I use similar if clauses with relational operators elsewhere. Thanks for your help in advance.
int foo(char *str1,char **str2, char **str3)
{
char *token1;
char *token2;
char *token = strtok(str1, "\"");
int spaces = strcmp(token," ");
int parenthesis = strcmp("{",token);
if((token == NULL) || ((spaces != 0) && (parenthesis != 0)))
{
printf("ERR.\n");
return 0;
}
token = strtok(NULL, "\"");
if(token == NULL)
{
printf("2ERR\n");
return 0;
}
token1= strtok(NULL, "\"");
if(token1 == NULL || strcmp(token1," -> ") != 0)
{
printf("3ERR\n");
return 0;
}
token2 = strtok(NULL, "\"");
return 1;
}
The strtok will crash if you don't use char[]. You can get around it using strcpy.
char str[80];
strcpy(str, str1);
char *token = strtok(str, "\"");
I'm not sure what you're trying to do, but your code will run without crashing after the small change.
#include <stdio.h>
#include <string.h>
int foo(char *str1,char **str2, char **str3)
{
char *token1;
char *token2;
char str[80];
strcpy(str, str1);
char *token = strtok(str, "\"");
int spaces = strcmp(token," ");
int parenthesis = strcmp("{",token);
if((token == NULL) || ((spaces != 0) && (parenthesis != 0)))
{
printf("ERR.\n");
return 0;
}
token = strtok(NULL, "\"");
if(token == NULL)
{
printf("2ERR\n");
return 0;
}
token1= strtok(NULL, "\"");
if(token1 == NULL || strcmp(token1," -> ") != 0)
{
printf("3ERR\n");
return 0;
}
token2 = strtok(NULL, "\"");
return 1;
}
int main() {
char * c1, * c2, * c3;
c1 = "foobaz";
c2 = "bar";
c3 = "baz";
int i = foo(c1, &c2, &c3);
return 0;
}
Related
How i can create a function for reading structure from a test.txt. I have a good works code in main, but i need to carry out it from main(). How combine (struct student PI1[N] and (fread() or fgets() or fwrite()));
struct student {
char surname[50];
char name[50];
char dayBirth[50];
int mark;
};
struct student PI1[N];
int main()
{
int counter = 0;
char str[50];
const char s[2] = " ";
char* token;
FILE* ptr;
int i = 0;
ptr = fopen("test.txt", "r");
if (NULL == ptr) {
printf("file can't be opened \n");
}
char* tmp;
int Itmp;
while (fgets(str, 50, ptr) != NULL) {
token = strtok(str, s);
strcpy(PI1[i].surname, token);
token = strtok(NULL, s);
strcpy(PI1[i].name, token);
token = strtok(NULL, s);
strcpy(PI1[i].dayBirth, token);
token = strtok(NULL, s);
Itmp = atoi(token);
PI1[i].mark = Itmp;
i++;
counter++;
}
}
Rather than "can create a function for reading structure from a test.txt", start with a function to convert a string from fgets() into a struct. Then call it as needed.
Use sprintf() and " %n" to detect complete scan with no extra text.
// Return success flag
bool string_to_student(struct student *stu, const char *s) {
int n = 0;
sscanf(s, "%49s%49s%49s%d %n", stu->surname, stu->name,
stu->dayBirth, &stu->mark, &n);
return n > 0 && s[n] == '\0';
}
Use
while (i < N && fgets(str, sizeof str, ptr) &&
string_to_student(&PI1[i], str)) {
i++;
}
counter = i;
I have to write this code, I mean I should read from the file name of students and their mark, and then sort students by the grow of mark. Now I just want to output only mark. I want to display grades using structures. I don't know where the problem is.
text.file
Jon 3
Alina 5
Ron 1
#include <stdio.h>
#define _CRT_SECURE_NO_WARNINGS
#include <string.h>
#include <stdlib.h>
int main()
{
const int N = 3;
int i = 0;
struct student {
char surname[50];
int mark;
};
struct student PI1[N];
char str[50];
const char s[1] = " ";
char* token;
FILE* ptr;
token = strtok(str, s);
ptr = fopen("test.txt", "r");
if (NULL == ptr) {
printf("file can't be opened \n");
}
while (fgets(str, 50, ptr) != NULL){
token = strtok(str, s);
strcpy(PI1[i].surname, token);
token = strtok(NULL, s);
PI1[i].mark = atoi(token);
i++;
}
fclose(ptr);
printf("The marks is:\n");
printf("%d %d %d", PI1[0].mark, PI1[1].mark, PI1[2].mark);
return 0;
}
You need to prevent the program from reading from the file pointer if opening the file fails:
ptr = fopen("test.txt", "r");
if (NULL == ptr) {
perror("test.txt");
return 1; // this could be one way
}
The second argument to strok should be a null terminated string. const char s[1] = " "; only has room for one character. No null terminator (\0). Make it:
const char s[] = " "; // or const char s[2] = " "; or const char *s = " ";
Don't iterate out of bounds. You need to check so that you don't try to put data in PI1[N] etc.
while (i < N && fgets(str, sizeof str, ptr) != NULL) {
// ^^^^^^^^
Check that strok actually returns a pointer to a new token. If it doesn't, the line you've read doesn't fulfill the requirements.
while (i < N && fgets(str, sizeof str, ptr) != NULL) {
token = strtok(str, s);
if(!token) break; // token check
strcpy(PI1[i].surname, token);
token = strtok(NULL, s);
if (token) // token check
PI1[i].mark = atoi(token);
else
break;
i++;
}
You could also skip the strcpy by reading directly into your struct student since char str[50]; has the same length as surname. str should probably be larger though, but for now:
while (i < N && fgets(PI1[i].surname, sizeof PI1[i].surname, ptr) != NULL) {
token = strtok(PI1[i].surname, s);
if(!token) break;
token = strtok(NULL, s);
if (token)
PI1[i].mark = atoi(token);
else
break;
i++;
}
Only print as many marks as you successfully read
printf("The marks are:\n");
for(int idx = 0; idx < i; ++idx) {
printf("%d ", PI1[idx].mark);
}
putchar('\n');
I am trying to write a simple Shell in C. Eventually, I will implement forking of processes and piping etc. But, right now, I'm just trying to get all the logic worked out.
I have a partially working shell: When I type exit it exits... however, my token function doesn't seem to be working right.
What am I doing wrong here? I'm not sure why its seg-faulting.
Token prints out once in the while loop and then it seg-faults and crashes.
#include <stdio.h>
#include <sys/wait.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
#define MAX_BUF_SZ 1024
void checkForPipe(char *string, bool *pipe_bool);
void checkForRedirect(char *string, bool *redirect_bool);
void tokenizeInput(char *string, bool pipe, bool redirect);
int main()
{
char *ptr;
bool is_pipe = 0;
bool is_redirect_out = 0;
bool is_exit = 0;
ptr = (char*)malloc(MAX_BUF_SZ);
while(!is_exit)
{
// Diplay prompt
char cur_dir[MAX_BUF_SZ];
getcwd(cur_dir, MAX_BUF_SZ);
printf("SHELL:%s$ ", cur_dir);
fgets(ptr, MAX_BUF_SZ, stdin);
checkForPipe(ptr, &is_pipe);
checkForRedirect(ptr, &is_redirect_out);
printf("pipe flag = %d\n", is_pipe);
printf("redirect flag = %d\n", is_redirect_out);
if(strcmp(ptr, "exit\n") == 0)
{
is_exit = 1;
}
tokenizeInput(ptr, is_pipe, is_redirect_out);
}
return 0;
}
void checkForPipe(char *string, bool *pipe_bool)
{
char *check_for_pipes;
char *clean_compare;
check_for_pipes = (char*)malloc(MAX_BUF_SZ);
clean_compare = (char*)malloc(MAX_BUF_SZ);
strcpy(check_for_pipes, string);
strcpy(clean_compare, string);
char * token = strtok(check_for_pipes, "|");
if(strcmp(token, clean_compare) == 0)
{
free(clean_compare);
free(check_for_pipes);
}
else
{
*pipe_bool = 1;
free(clean_compare);
free(check_for_pipes);
}
}
void checkForRedirect(char *string, bool *redirect_bool)
{
char *check_for_redirects;
char *clean_compare;
check_for_redirects = (char*)malloc(MAX_BUF_SZ);
clean_compare = (char*)malloc(MAX_BUF_SZ);
strcpy(check_for_redirects, string);
strcpy(clean_compare, string);
char * token = strtok(check_for_redirects, ">");
if(strcmp(token, clean_compare) == 0)
{
free(clean_compare);
free(check_for_redirects);
}
else
{
*redirect_bool = 1;
free(clean_compare);
free(check_for_redirects);
}
}
void tokenizeInput(char *string, bool pipe, bool redirect)
{
char *copy_string;
copy_string = (char*)malloc(MAX_BUF_SZ);
strcpy(copy_string, string);
if(pipe == 0 && redirect == 0)
{
char **args = {NULL};
char *token = strtok(copy_string, " ");
int i = 0;
printf("%s\n", token);
while(token != NULL)
{
args[i] = token;
strtok(NULL, " ");
printf("%s\n", token);
i++;
}
}
/* printf("%s\n%s\n%s\n", args[0], args[1], args[2]); */
}
The problem is on args[i]
I modified your code as follows:
Supposing you have a pre-known number of token which is MAX_BUF_SZ.
You allocate MAX_BUF_SZ pointers of type char*
char **args = malloc(MAX_BUF_SZ * sizeof(char *));
and in the loop, you still have to allocate each pointer char* before using it:
while(token != NULL)
{
args[i] = (char *)malloc(strlen(token)+1);
printf("%s\n", token);
args[i] = token;
token = strtok(NULL, " ");
i++;
}
The whole functions is like this:
void tokenizeInput(char *string, bool pipe, bool redirect)
{
char *copy_string;
copy_string = (char*)malloc(MAX_BUF_SZ);
strcpy(copy_string, string);
// suppose we would have MAX_BUF_SZ tokens
char **args = malloc(MAX_BUF_SZ * sizeof(char *));
if(pipe == 0 && redirect == 0)
{
char *token = strtok(copy_string, " ");
int i = 0;
//printf("token %s\n", token);
while(token != NULL)
{
args[i] = (char *)malloc(strlen(token)+1);
printf("%s\n", token);
args[i] = token;
token = strtok(NULL, " ");
i++;
}
}
/* printf("%s\n%s\n%s\n", args[0], args[1], args[2]); */
}
Here is my example running :
SHELL:D:\Users\T0180694\Documents\Mes Outils Personnels\PAN\PAN_folder$ test is essai of you and me
pipe flag = 0
redirect flag = 0
test
is
essai
of
you
and
me
I have been trying to write a code to remove a word from an inputted string as part of my homework. But the thing is the outputted "modified" string never really gets modified and it actually always outputs the inputted string. I'm new to strings so I don't have a perfect understanding of how the string.h library functions work.
#include<stdio.h>
#include<string.h>
int main(void)
{
char str[60], strtemp[60], word[10], * token;
printf("Enter the sentence: ");
gets_s(str);
printf("Enter the word to be deleted: ");
gets_s(word);
int i = 0;
token = strtok(str, " ");
while (token != NULL) {
if (!i && token != word)
strcpy(strtemp, token);
else if (token == word) {
token = strtok(NULL, " ");
continue;
}
else {
strcat(strtemp, " ");
strcat(strtemp, token);
}
token = strtok(NULL, " ");
i++;
}
strcpy(str, strtemp);
printf("Modified string: %s \n", str);
}
Add the following:
char *strremove(char *str, const char *sub) {
size_t len = strlen(sub);
if (len > 0) {
char *p = str;
while ((p = strstr(p, sub)) != NULL) {
memmove(p, p + len, strlen(p + len) + 1);
}
}
return str;
}
You should use the memmove() (written on your post's comment too.)
Reference: this thread of SO.
I'm writing a basic program that takes a CSV file, prints the first field, and does some numerical evaluation of the other fields.
I'm looking to put all the numerical fields into an array but every time I do this and try to access a random element of the array, it prints the entire thing
My CSV file is:
Exp1,10,12,13
Exp2,15,16,19
and i'm trying to access the second field so it prints
Exp1 12
Exp2 16
but instead I'm getting
Exp1 101213
Exp2 151619
If someone could provide some suggestions. This is my code:
#define DELIM ","
int main(int argc, char *argv[])
{
if(argc == 2) {
FILE *txt_file;
txt_file = fopen(argv[1], "rt");
if(!txt_file) {
printf("File does not exist.\n");
return 1;
}
char tmp[4096];
char data[4096];
char expName[100];
char *tok;
int i;
while(1){
if(!fgets(tmp, sizeof(tmp), txt_file)) break;
//prints the experiment name
tok = strtok(tmp, DELIM);
strncpy(expName, tok, sizeof(expName));
printf("\n%s ", expName);
while(tok != NULL) {
tok = strtok(NULL, DELIM);
//puts data fields into an array
for(i=0; i < sizeof(data); i++) {
if(tok != NULL) {
data[i] = atoi(tok);
}
}
printf("%d", data[1]);
}
}
fclose(txt_file);
return 0;
}
sample to fix
char tmp[4096];
int data[2048];
char expName[100];
char *tok;
int i=0;
while(fgets(tmp, sizeof(tmp), txt_file)){
tok = strtok(tmp, DELIM);
strncpy(expName, tok, sizeof(expName));
printf("\n%s ", expName);
while((tok = strtok(NULL, DELIM))!=NULL){
data[i++] = atoi(tok);
}
printf("%d", data[1]);
i = 0;
}
A modified code snippet:
int data[20]; // change 20 to a reasonable value
...
while (1)
{ if (!fgets(tmp, sizeof(tmp), txt_file))
break;
//prints the experiment name
tok = strtok(tmp, DELIM);
strncpy(expName, tok, sizeof(expName));
printf("\n%s ", expName);
i = 0;
tok = strtok(NULL, DELIM);
while (tok != NULL)
{ //puts data fields into an array
data[i++] = atoi(tok);
if (i == 20)
break;
tok = strtok(NULL, DELIM);
}
if (i > 1)
printf("%d", data[1]);
}