if/else doesn't behave as expected - c

I have been working on a little test program which reads some values from a config file into variables however it seems I get odd behavior with if/else statements. For instance if I run this and print out the processed variables I get that sectorloop is 20000 even though it is defined in my cfg as 100000. I know it detects it because If I remove the else statement after the strcmp() for driveamount it works fine. This would however break the fallback if it isn't defined in the test.cfg...
int sectorloop,driveamount,q,j,p;
char cfgstring[3][128],sys_serial[128];
/*
the analyzing is broken up into 6 steps:
1: read test.cfg data into an 2d array of chars with newlines as delimiter.
2. go through each value in the array and look for the '=' this is the delimiter for the meaning=value.
3. overwrite '=' to a string terminating character '\0' C thinks the meaning specifier is the entire string while still keeping the value in memory allthough hidden
4. use string compare to match to meaning to the desired string.
5. if there is a match move the value(after the '=' in the config) to the beginning of the array. overwriting the meaning as it isn`t needed anymore
6. now we have a string which we know what meaning it belonged to and can use it in the program, sometimes it needs to be converted to int or whatever
*/
FILE *configfp=fopen("test.cfg","r");
if (configfp==NULL) {
sectorloop=50000;
driveamount=27;
sys_serial[0]='\0';
} else {
q=j=0;while ((cfgstring[j][q]=fgetc(configfp))!=EOF&&q<128&&p<3) {
if (cfgstring[j][q]==10||cfgstring[j][q]==13) {
cfgstring[j][q]='\0';
q=0;
j++;
}
else {
q++;
}
}
cfgstring[j][q]='\0';
for (q=0;q<=j;q++) {
p=0;while (cfgstring[q][p]!='='&&cfgstring[q][p]!='\0'&&p<128) {
p++;
}
cfgstring[q][p]='\0';
if ((strcmp(cfgstring[q],"host_serial"))==0) {
j=0;while (cfgstring[q][j+p+1]!='\0') {
cfgstring[q][j]=cfgstring[q][j+p+1];
j++;
}
cfgstring[q][j]='\0';
strcpy(sys_serial,cfgstring[q]);
}
if ((strcmp(cfgstring[q],"sectorloop"))==0) {
j=0;while (cfgstring[q][j+p+1]!='\0') {
cfgstring[q][j]=cfgstring[q][j+p+1];
j++;
}
cfgstring[q][j]='\0';
if ((sectorloop=atoi(cfgstring[q]))==0) {
sectorloop=50000;
}
} else {
sectorloop=20000;
}
if ((strcmp(cfgstring[q],"driveamount"))==0) {
j=0;while (cfgstring[q][j+p+1]!='\0') {
cfgstring[q][j]=cfgstring[q][j+p+1];
j++;
}
cfgstring[q][j]='\0';
if ((driveamount=atoi(cfgstring[q]))==0) {
driveamount=27;
}
} else {
driveamount=27;
}
}
}
fclose(configfp);
the cfg look like this:
host_serial=serial number
sectorloop=100000
driveamount=33

Your code logic is wrong. Basically, your code does this:
for each config string:
if string == "sectorloop"
sectorloop = value from string
else
sectorloop = default value
if string == "driveamount"
driveamount = value from string
else
driveamount = default value
Now say your input is "sectorloop=x; driveamount=y". The first pass will assign x to sectorloop and the default value to driveamount. The next pass will overwrite sectorloop with the default and assign y to driveamount.
You'll want something like this:
sectorloop = default value
driveamount = default value
for each config string:
if string == "sectorloop"
sectorloop = value from string
if string == "driveamount"
driveamount = value from string

Related

Is there something that avoids some characters (1, f, x, and b, specifically) to be validated from an input?

I have a field to validate repeated questions. I must convert special characters into normal letters using a method, and then I use a method to skip spaces and other characters to validate if the new text is equal to the existing questions. In my local everything is working fine, but in a Production instance, it skips characters 1, f, x and b. My project in Production is mounted in Linux.
My two methods are:
replaceSpecialCharacters(output){
return output = output.replace(/á|é|í|ó|ú|ñ|ä|ë|ï|ö|ü|à|è|ì|ò|ù/ig,function (str,offset,s) {
var str = str=="á"?"a":str=="é"?"e":str=="í"?"i":str=="ó"?"o":str=="ú"?"u":str=="ñ"?"n":str;
str = str=="Á"?"A":str=="É"?"E":str=="Í"?"I":str=="Ó"?"O":str=="Ú"?"U":str=="Ñ"?"N":str;
str = str=="à"?"a":str=="è"?"e":str=="ì"?"i":str=="ò"?"o":str=="ù"?"u":str;
str = str=="À"?"A":str=="È"?"E":str=="Ì"?"I":str=="Ò"?"O":str=="Ù"?"U":str;
str = str=="ä"?"a":str=="ë"?"e":str=="ï"?"i":str=="ö"?"o":str=="ü"?"u":str;
str = str=="Ä"?"A":str=="Ë"?"E":str=="Ï"?"I":str=="Ö"?"O":str=="Ü"?"U":str;
return (str);
});
}
validateRepeatedQuestion(question): void {
var questionToCheck = this.replaceSpecialCharacters(question).replace(/[(\s)+(\¿)+(\?)+(\¡)+(\!)+(\")+(\')+]/g, "");
this.setState({isRepeated: false});
for (let i = 0; i < this.props.allQuestions.length; i++) {
var questionFromArray = this.replaceSpecialCharacters(this.props.allQuestions[i].text).replace(/[(\s)+(\¿)+(\?)+(\¡)+(\!)+(\")+(\')+]/g, "");
if(this.props.allQuestions[i].position != this.props.question.position){
if(questionFromArray.toLocaleLowerCase() == questionToCheck.toLocaleLowerCase()){
this.setState({isRepeated: true});
}
}
}
}
If I have a question like "How old are you?" and I try to add a question like "How old are you?1111" I expect the validation to take the new question as different, but the actual output says that the question is repeated, even if I'm adding numbers 1. It must be different.

Reaching from one string to another using given dictionary

For this question, a dictionary was given and two strings also given, it was basically asked to reach from one string to another one just using the words in dictionary, and only one letter can be changed at a time. I came up with this solution. There were some corner cases that my code can not handle. Can you help to find all the corner cases to make this code prettier?
public static int findNumberOfSteps(String start, String end , HashSet<String> dict){
if( start == null || end == null || dict.isEmpty()){
throw new IllegalArgumentException();
}
dict.add(end);
Queue<String> wordHolder = new LinkedList<>();
Queue<Integer> distanceCount = new LinkedList<Integer>();
wordHolder.add(start);
distanceCount.add(1);
int result = Integer.MAX_VALUE;
while (!wordHolder.isEmpty()){
String currentWord = wordHolder.poll();
int currDistance = distanceCount.poll();
if(currentWord.equals(end)){
int result = currDistance;
return result;
}
for (int i = 0 ; i < currentWord.length() ; i++){
char[] charCurrentWord = currentWord.toCharArray();
for ( char c = 'a' ; c <= 'z' ; c++){
charCurrentWord[i] = c;
String newWord = new String(charCurrentWord);
if (dict.contains(newWord)){
wordHolder.add(newWord);
distanceCount.add(currDistance+1);
dict.remove(newWord);
}
}
}
}
return 0;
}
There are a couple of problems in the code. The first problem is in this code
if(currentWord.equals(end)){
result = Math.min(result, currDistance);
}
Note that when you reach the end word, that code updates the result, but then the code is going to search for ways to change the end word to something else. That's a huge waste of time, the code should continue with the while(!wordHolder.isEmpy()) loop after the end is found.
The second problem is in this code
if (dict.contains(newWord)){
wordHolder.add(newWord);
distanceCount.add(currDistance+1);
dict.remove(newWord);
}
Note that if newWord is equal to the end word, then that code removes the end word from the dictionary, which means that you'll never find the end word again.
The solution to both problems is to check for the end word inside that if statement. When the end is found, don't add it to the wordHolder and don't remove it from the dictionary.
if (dict.contains(newWord)){
if(newWord.equals(end)){
result = Math.min(result, currDistance+1);
}
else{
wordHolder.add(newWord);
distanceCount.add(currDistance+1);
dict.remove(newWord);
}
}

Search element in array

I'm creating an Address Book program using array. I've done with the add and print data option. But now I'm stuck with the search/update option.
This is my code in searching for the element if it exist in my array or not.
public void update_data(){
String user_input_data;
int search_data = 0;
System.out.println("Enter the data that you want to search: ");
user_input_data = user_data.nextLine();
while(search_data<data_recorded){
if(user_input_data == AddressBook_Array_name[search_data])
{
System.out.println("Data found!");
}
else
{
System.out.println("Data not found!");
}
search_data++;
}
}
But when I run the program. It always return to false and print the else statement.
I don't know what's wrong with it. Anyway the data_recorded variable holds the number of data inputted by the user in the add option.
You need to use equals() instead of == in java for comparision.
if (user_input_data.equals(AddressBook_Array_name[search_data]))
Also, instead of the while you may want to use the foreach loop (removes the need for search_data variable).
for(String addressBookElem : AddressBook_Array_name) {
if (user_input_data.equals(addressBookElem)) {
System.out.println("Data found!");
return;
}
}
System.out.println("Data not found!"); // reaches this statement if data not present
i think you should use .equals function instead of ==.

My strcmp doesn't return 0 when it should

Context : I'm searching for all the words contained in a 2d array (horizontally,vertically and diagonaly).
So what I do is I get all the possible words, check if they're in the given dictionary and if they are store them in an array. The thing is, I don't want it to have duplicates.
Here's a snippet of the code:
for (i=l-1;i>=0;i--){
palavra[aux]=mat[i][caux];
for (j=i;j>=0;j--){
palavra[aux]=mat[j][caux];
palavra[aux+1]='\0';
for (it=0;encontradas[it]!=NULL;it++){
if (strcmp(palavra,encontradas[it])==0)flag=1;
else flag=0;
}
if (flag==0) {
r = palavra_existe(dic,palavra);
if (r!=0) {
found[auxenc]=mystrdup(palavra);
auxenc++;
}
}
flag=0;
aux++;
}
aux=0;
}
The
if (strcmp(palavra, found[it])==0)flag=1
line is there to check if the formed worded has been found already, to avoid creating a duplicate. The problem is it doesn't work, duplicates appear anyway (as the flag variable never takes the value 1).
What could I be missing here?
The flag variable does get the value 1, but then it turns back to 0 again in the next iteration.
Set flag to zero before the loop, and when you find a match you set it to 1 and exit the loop:
flag = 0;
for (it = 0; encontradas[it] != NULL; it++) {
if (strcmp(palavra,encontradas[it]) == 0) {
flag=1;
break;
}
}
(Exiting the loop isn't needed for the logic to work, but there is no point in looping through the rest of the items once you have found a match.)

Why can't I populate and return my array created with rb_ary_new?

I'm not able to insert values into a Ruby array, and retrieve them later.
I put the results of different lines that I tried inside the first function. The results are:
VALUE rStraightCards;
static VALUE check_for_straight() {
stuff...
if (begin_straight != NOT_FOUND) {
for (i = begin_straight; i >= end_straight; i--) {
// this gives me a segmentation fault when I call straight_cards()
rb_ary_push(rStraightCards, i);
// these lines give me an empty ary when I call straight_cards()
// RARRAY_PTR(rStraightCards)[i] = i;
// RARRAY_PTR(rStraightCards)[INT2NUM(i)] = INT2NUM(i);
}
}
}
VALUE straight_cards() {
return rStraightCards;
}
void Init_straight_count() {
rStraightCards = rb_ary_new2(NUM_CARDS);
}
Both arguments for rb_ary_push are supposed to be of type VALUE but you're pushing an int (probably):
VALUE
rb_ary_push(VALUE ary, VALUE item)
{
rb_ary_modify(ary);
return rb_ary_push_1(ary, item);
}
Try this:
rb_ary_push(rStraightCards, INT2NUM(i));
I think it is worth noting that VALUE will usually be defined like this:
typedef uintptr_t VALUE;
So the usual warning flags for int-to-pointer conversions won't catch this sort of error.

Resources