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
I am new to programming and this one has me baffled.
I am writing a function to be called by main that takes the command line arguments and stores them in a struct to use later. This specific example is for use with image editing, but can be used anywhere.
Desired performance: Function takes arguments from the command line. Three specific arguments are identified and checked for: -h, -o and -t. If present they will alter the struct values. Arguments -o and -t store the arguments immediately following them into their respective struct fields. Any argument that is not -h or does not have -o or -t preceding it is assumed to be the input file name and stored in flag->inputFile. If all arguments are accounted for, then flag->inputFile should remain NULL and can be tested for in the main function and program terminated if this is true.
Problem: When there is no input file specified (using the above parameters) flag->inputFile keeps getting set to -o when it is included as an argument.
Solution: Thanks to Scott this question has been answered by replacing several if statements with else if has now seemed to fix the problem, and the function appears to be working as desired.
My understanding of what was happening is that the else statement was being run in every iteration of i unless the -t argument was included, since it was the statement immediately before the else
The compiler I'm using is gcc and this is my code. (I know my struct is not packed, I'm still trying to get my head around this and can't see how it would result in what I'm seeing. Segmentation fault, yes, but not this?)
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
struct PROMPTFLAGS {
int help; // Change from NULL if -h argument present
char * outputFile; // Store argument after -o as the output file
char * inputFile; // Argument not paired with a flag stored here as input file
float threshold; // Stores a value to use in image manipulation in main
};
struct PROMPTFLAGS * parsargs(int argc, char * argv[]) {
struct PROMPTFLAGS* flag = malloc(sizeof(struct PROMPTFLAGS));
int i;
printf("argc: %d\n",argc);
for (i = 1; i < argc; i++) {
char * arg = argv[i];
int str_aft = i+1; // Allows the next string to be used in this iteration of the loop
if (strcmp(arg,"-h") == 0) {
flag->help = 1;
}
if (strcmp(arg,"-o") == 0) { // Changing this to 'else if' seems to be a fix
flag->outputFile = argv[str_aft];
i++; // Skips over next arg since already read by argv[str_aft]
}
if (strcmp(arg,"-t") == 0) { // Changing this to 'else if' seems to be a fix
flag->threshold = strtod(argv[str_aft],NULL);
i++; // Skips over next arg since already read by argv[str_aft]
}
else {
flag->inputFile = arg;
}
}
return flag;
}
int main(int argc, char* argv[]) {
struct PROMPTFLAGS * flags;
flags = parsargs(argc, argv);
printf("Help = %d\n",flags.help);
printf("Output = %s\n",flags.outputFile);
printf("Input = %s\n",flags.inputFile);
printf("Threshold = %s\n",flags.threshold);
return 0;
}
I apologise for the poor format of the first version of this question and hope that this edit is better. I have made the functions' desired outcomes and the problem I encountered clearer and removed most of the test prints I had through the code and added some comments. I have also included the solution to my problem (provided by another user) and my understanding of what was happening in the broken code.
If people still think this is a poor question or of no use to anyone else then I'm happy to take it down, but have edited and left it up hoping it can help someone else.
This is my first post on stack overflow and I thank everyone for their help and patience while I learn to code and the best manner to post questions.
You set flag->inputFile = arg whenever arg is not "-t" (the else after testing for "-t"). I'm not sure when you want to assign to this field, but I am sure this isn't the right logic for it. For example, if you wanted to do this when arg is none of the other specific flags you are looking for, you should be using if ... else if ... else if ... else.
Related
I seem to be losing the end of my string after the exit of the for loop in the function below. Any help would be very much appreciated.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
char *get_out_file_name(int in_file_num);
int main(int argc, char *argv[])
{
char* file_name = get_out_file_name(37);
printf("name_final = %s \n", file_name);
free (file_name);
}
char *get_out_file_name(int in_file_num)
{
const int max_name_length = 3;
const int file_type_length = 4;
const char *type_suffix;
type_suffix = ".jpg";
int num_remainder = in_file_num;
char * name_final = malloc(sizeof(char) * (max_name_length + file_type_length + 1));
for (int i = max_name_length - 1; i >= 0 ; i --)
{
printf("i = %d\n",i);
name_final[i] = num_remainder % 10;
sprintf (&name_final[i], "%d", name_final[i]);
printf("name_final[i] = %c \n", name_final[i]);
num_remainder /= 10;
}
printf("pre concat[1] = %c \n",name_final[1]);
strcat(name_final, type_suffix);
// printf("name_final %s \n", name_final);
return name_final;
}
The only place the data is retained is in name_final[0], array index 1 and 2 hold no data after the exit of the for loop.
I'm thinking it's possibly sprintf creates it's own local copy in the for loop or that I'm missing a reference/dereference somewhere. I was hoping someone could clarify.
The output is in the screenshot below. Apologies for the quality of the output screen grab. I'm having to use my phone to post.
I've just had chance to work out this function properly and wanted to give an explanation in case anyone stumbles across this in the future.
When I wrote that code I didn't understand how to convert a char by adding 0. I understand now that we don't actually add the value 0. We add the value 48 as this is the ASCII number/index for 0. All this is due to chars being saved as integers by c.
I'm trying to use realloc function in C, to dynamically operate on a char array of strings (char**).
I usually get a realloc():invalid old size error after 41st cicle of the for loop and I really can't understand why.
So, thanks to everyone who will help me ^-^
[EDIT] I'm trying to make the post more clear and following your advices, as a "new active member" of this community, so thank you all!
typedef struct _WordsOfInterest { // this is in an header file containing just
char **saved; // the struct and libraries
int index;
} wordsOfInterest;
int main() {
char *token1, *token2, *save1 = NULL, file[LEN], *temp, *word, **tokenArr;
int n=0, ch,ch2, flag=0, size, init=0,position,currEdit,init2=0,tempEdit,size_arr=LEN,
oldIndex=0,totalIndex=0,*editArr,counterTok=0;
wordsOfInterest toPrint;
char **final;
toPrint.index = 0;
toPrint.saved = malloc(sizeof(char*)*LEN);
editArr = malloc(sizeof(int)*LEN);
tokenArr = malloc(sizeof(char*)*LEN);
final = malloc(sizeof(char*)*1);
// external for loop
for(...) {
tokenArr[counterTok] = token1;
// internal while loop
while(...) {
// some code here surely not involved in the issue
} else {
if(init2 == 0) {
currEdit = config(token1,token2);
toPrint.saved[toPrint.index] = token2;
toPrint.index++;
init2 = 1;
} else {
if((abs((int)strlen(token1)-(int)strlen(token2)))<=currEdit) {
if((tempEdit = config(token1,token2)) == currEdit) {
toPrint.saved[toPrint.index] = token2;
toPrint.index++;
if(toPrint.index == size_arr-1) {
size_arr = size_arr*2;
toPrint.saved = realloc(toPrint.saved, size_arr);
}
} else if((tempEdit = config(token1,token2))<currEdit) {
freeArr(toPrint, size_arr);
toPrint.saved[toPrint.index] = token2;
toPrint.index++;
currEdit = tempEdit;
}
}
}
flag = 0;
word = NULL;
temp = NULL;
freeArr(toPrint, size_arr);
}
}
editArr[counterTok] = currEdit;
init2 = 0;
totalIndex = totalIndex + toPrint.index + 1;
final = realloc(final, (sizeof(char*)*totalIndex));
uniteArr(toPrint, final, oldIndex);
oldIndex = toPrint.index;
freeArr(toPrint,size_arr);
fseek(fp2,0,SEEK_SET);
counterTok++;
}
You start with final uninitialized.
char **final;
change it to:
char **final = NULL;
Even if you are starting with no allocation, it needs a valid value (e.g. NULL) because if you don't initialize a local variable to NULL, it gets garbage, and realloc() will think it is reallocating a valid chunk of memory and will fail into Undefined Behaviour. This is probably your problem, but as you have eliminated a lot of code in between the declaration and the first usage of realloc, whe cannot guess what is happening here.
Anyway, if you have indeed initialized it, I cannot say, as you have hidden part of the code, unlistening the recommendation of How to create a Minimal, Reproducible Example
.
There are several reasons (mostly explained there) to provide a full but m inimal, out of the box, failing code. This allows us to test that code without having to provide (and probably solving, all or part) the neccesary code to make it run. If you only post a concept, you cannot expect from us complete, full running, and tested code, degrading strongly the quality of SO answers.
This means you have work to do before posting, not just eliminating what you think is not worth mentioning.
You need to build a sample that, with minimum code, shows the actual behaviour you see (a nonworking complete program) This means eliminating everything that is not related to the problem.
You need (and this is by far more important) to, before sending the code, to test it at your site, and see that it behaves as you see at home. There are many examples that, when eliminated the unrelated code, don't show the commented behaviour.
...and then, without touching anymore the code, send it as is. Many times we see code that has been touched before sending, and the problem dissapeared.
If we need to build a program, we will probably do it with many other mistakes, but not yours, and this desvirtuates the purpose of this forum.
Finally, sorry for the flame.... but it is necessary to make people read the rules.
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 5 years ago.
Improve this question
I'm building a system of 2 servers and 1 client for reservations.
I found an obstacle, now I'll explain:
-server A
-server B
-client
Once the client selects from a menu what he wants to book and when,
server B must look in the struct for the date and check if it is available, if it is send an ok, if it is not send a no as an answer.
To do it I had thought of the following way, but it does not work:
bool search(int bet2, bool flag)
{
int i=0;
for(i=0; i < 11; i++){
if(strcmp(content[i].date, content[bet2].date) == 0)
{
if (content[i].mark == true)
{
printf("Date Busy");
return false;
} else {
content[i].mark = true;
printf("Date booked day: %s",content[i].date);
return true;
}}
}
}
in the prototypes I declare it so:
bool search (int bet2, bool flag);
in the main I declare it so:
search (bet2, flag);
the struct is this:
typedef struct choice {
char name [40];
char date [40];
bool mark;
} Choice;
Choice content [10];
now I have a doubt, but the type bool exists in C?
anyway, where am I wrong?
sorry but I'm writing lines of code this morning and I'm stuck here, probably I do not see it.
this code return ever that date is good, where am i wrong?
content [i] .mark = true
will be
content [i] .mark == true
To avoid this kind of problem you can use the comparison like this
true == content [i] .mark
In this case even if you forget the == and use = the compiler will complain.
And yes even better is to use simple and easy to read
if( content [i] .mark )
Also there is no keyword called Else in C. It will be else.
Remove the extra } in the code where you have written }}. The scoping changes for that and it is wrong.
Also why use return flag = false it's useless here. Just do return false or return true. Because flag's changed value won't be used anywhere.
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 7 years ago.
Improve this question
I tried to build and run the following program, but it breaks down executing. I thought maybe I made a mistake but 0 errors and 0 warnings were shown.
After researching such behavior on stackoverflow, I mostly saw some misplaced semicolons or forgotten address-operators, which I do not see in this source code or am I overlooking something?
Could some C or GCC Guru tell me what is wrong and why?
Operating system is Windows 7, and compiler had enabled:
-pedantic -w -Wextra -Wall -ansi
Here is the source code:
#include <stdio.h>
#include <string.h>
char *split(char * wort, char c)
{
int i = 0;
while (wort[i] != c && wort[i] != '\0') {
++i;
}
if (wort[i] == c) {
wort[i] = '\0';
return &wort[i+1];
} else {
return NULL;
}
}
int main()
{
char *in = "Some text here";
char *rest;
rest = split(in,' ');
if (rest == NULL) {
printf("\nString could not be devided!");
return 1;
}
printf("\nErster Teil: ");
puts(in);
printf("\nRest: ");
puts(rest);
return 0;
}
The expected behavior is that the string "Some text here" is split at its first space ' ' and the expected output would be:
Erster Teil: Some
Rest: text here
You are modifying a string literal, that's undefined behavior. Change this
char* in = "Some text here";
to
char in[] = "Some text here";
This makes in an array and initializes it with "Some text here". You should use const to prevent accidentally having this bug when you define a pointer to a string literal.
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
Why I am getting runtime error (SIGSEGV) on the following code:
#include<stdio.h>
#include<string.h>
int main()
{
int t_line,count[10000],i;
scanf("%d",&t_line);
for(i=1;i<=t_line;i++)
{
fflush(stdin);
gets(t);
count[i]=(int)t[0]+(int)t[1]+(int)t[2];
}
for(i=1;i<=t_line;i++)
printf("%d\n",count[i]);
return 0;
}
I have also tried to solve this problem by initialized all the elements of array.
I am wondering how the code compiled, without declaration of the variable t. But, still the only missing elemnt was: char t[your choice of size];. Apart from that
#include<stdio.h>
//#include<string.h> No need of this header,a s you are not using any string functions
int main()
{
int t_line,count[10000],i;
char t[64];//you need to declare the variable before using it
scanf("%d",&t_line);
//Its safer if you check this
if(t_line >= 10000)//if you use 0 and < t_line in for loop below then change the condition to: if(t_line > 10000)
{
printf("ERROR: Limit exceeded. Not enough memory.\n");
return 1;//or you could use exit(1); and #include <stdlib.h>
}
for(i=1;i<=t_line;i++)//suggested: for(i=0;i<t_line;i++)
{
//fflush(stdin);
//gets(t);
char *rc = fgets(t, sizeof(t), stdin);
if(rc != NULL)
{ t[strlen(t) - 1] = '\0';\\because fgets gets the \n into the string too. This line makes fgets similar to gets, improving safety from overflow.
}
else
{
// handle fgets failed error
}
count[i]=(int)t[0]+(int)t[1]+(int)t[2];
}
for(i=1;i<=t_line;i++)//suggested: for(i=0;i<t_line;i++)
printf("%d\n",count[i]);
return 0;
}
Find the solution and suggested changes inline as code comments.
In C, its better to use indexes starting from 0, unless there is a specific requirement to use other values.