Program that checks if an array contains all the elements it's supposed to contain [closed]












0














I wrote a Program that gets the input from a txt file and stores the input in an array.
After that I remove the spaces from each string so that it's easier for me to compare the string values in the array reds against the string value in the array string card.



The array red must contain all the elements of the array stringcard or else an error message will be printed. It doesn't matter if the elements in the input file are in order.



#include <stdio.h> 
#include <string.h>
#include <stdlib.h>
#define max 13
#define stringlength 8

//removes spaces
char * removechar(char str, int ch) {

char * cpos = str;

while ((cpos = strchr(cpos, ch))) {
strcpy(cpos, cpos + 1);
}
return str;
}

int all_match( char **table1, const char **table2, size_t t1size, size_t t2size)
{
for(size_t t1index = 0; t1index < t1size; t1index++)
{
int match = 0;
for(size_t t2index = 0; t2index < t2size; t2index++)
{
match = match || !strcmp(table1[t1index], table2[t2index]);
if(match) {
break;
}
}
if(!match){
printf("error");
return 0;
}
}
return 1;
}

int main(int argc, char ** argv) {

const char *stringcard = {
"REDAn",
"RED2n",
"RED3n",
"RED4n",
"RED5n",
"RED6n",
"RED7n",
"RED8n",
"RED9n",
"RED10n",
"REDJn",
"REDQn",
"REDKn",

};



char * reds[max];

int i;

FILE * file = argc > 1 ? fopen(argv[1], "r") : stdin;
if (file == NULL)
return 1;
if (argc != 2) {
printf("[ERR]");
return 0;
}

for (i = 0; i < max; i++) {

reds[i] = malloc(stringlength);
fgets(reds[i], stringlength, file);

}




for (i = 0; i < max; i++) {

printf("%s", reds[i]);

}

// removes spaces
for (i = 0; i < max; i++) {
removechar(reds[i], ' ');


}

for (i = 0; i < max; i++) {

printf("%s", reds[i]);

}


size_t size = sizeof(stringcard) / sizeof(stringcard[0]);
size_t size2 = sizeof(reds) / sizeof(reds[0]);

all_match(reds,stringcard,size,size2);

for (i = 0; i < max; i++) {

free(reds[i]);

}

return 0;

}


input:



RED A
RED 2
RED 3
RED 4
RED 5
RED 6
RED 7
RED 8
RED 9
RED 10
RED J
RED Q
RED K


This code works fine as long as the input-file looks like that.



If the input file looks like this:



RED A
RED 2

RED 3
RED 4
RED 5

RED 6
RED 7
RED 8
RED 9
RED 10
RED J

RED Q

RED K


I get an error. I guess the newlines in between are causing the problem.
Is there anyway to improve my Code?










share|improve this question







New contributor




momonosuke is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.











closed as off-topic by Sᴀᴍ Onᴇᴌᴀ, vnp, Zeta, Vogel612 Dec 22 at 12:16


This question appears to be off-topic. The users who voted to close gave this specific reason:


  • "Code not implemented or not working as intended: Code Review is a community where programmers peer-review your working code to address issues such as security, maintainability, performance, and scalability. We require that the code be working correctly, to the best of the author's knowledge, before proceeding with a review." – Sᴀᴍ Onᴇᴌᴀ, vnp, Zeta, Vogel612

If this question can be reworded to fit the rules in the help center, please edit the question.









  • 1




    Welcome to Code Review. Unfortunately, this question does not match what this site is about. Code Review is about improving existing, working code. Code Review is not the site to ask for help in fixing or changing what your code does. Once the code does what you want, we would love to help you do the same thing in a cleaner way! Please see our help center for more information. That being said, if you're fine with a review of your current version that doesn't support newlines, edit your question to remove the broken example and state the input format. Thanks!
    – Zeta
    Dec 22 at 8:49
















0














I wrote a Program that gets the input from a txt file and stores the input in an array.
After that I remove the spaces from each string so that it's easier for me to compare the string values in the array reds against the string value in the array string card.



The array red must contain all the elements of the array stringcard or else an error message will be printed. It doesn't matter if the elements in the input file are in order.



#include <stdio.h> 
#include <string.h>
#include <stdlib.h>
#define max 13
#define stringlength 8

//removes spaces
char * removechar(char str, int ch) {

char * cpos = str;

while ((cpos = strchr(cpos, ch))) {
strcpy(cpos, cpos + 1);
}
return str;
}

int all_match( char **table1, const char **table2, size_t t1size, size_t t2size)
{
for(size_t t1index = 0; t1index < t1size; t1index++)
{
int match = 0;
for(size_t t2index = 0; t2index < t2size; t2index++)
{
match = match || !strcmp(table1[t1index], table2[t2index]);
if(match) {
break;
}
}
if(!match){
printf("error");
return 0;
}
}
return 1;
}

int main(int argc, char ** argv) {

const char *stringcard = {
"REDAn",
"RED2n",
"RED3n",
"RED4n",
"RED5n",
"RED6n",
"RED7n",
"RED8n",
"RED9n",
"RED10n",
"REDJn",
"REDQn",
"REDKn",

};



char * reds[max];

int i;

FILE * file = argc > 1 ? fopen(argv[1], "r") : stdin;
if (file == NULL)
return 1;
if (argc != 2) {
printf("[ERR]");
return 0;
}

for (i = 0; i < max; i++) {

reds[i] = malloc(stringlength);
fgets(reds[i], stringlength, file);

}




for (i = 0; i < max; i++) {

printf("%s", reds[i]);

}

// removes spaces
for (i = 0; i < max; i++) {
removechar(reds[i], ' ');


}

for (i = 0; i < max; i++) {

printf("%s", reds[i]);

}


size_t size = sizeof(stringcard) / sizeof(stringcard[0]);
size_t size2 = sizeof(reds) / sizeof(reds[0]);

all_match(reds,stringcard,size,size2);

for (i = 0; i < max; i++) {

free(reds[i]);

}

return 0;

}


input:



RED A
RED 2
RED 3
RED 4
RED 5
RED 6
RED 7
RED 8
RED 9
RED 10
RED J
RED Q
RED K


This code works fine as long as the input-file looks like that.



If the input file looks like this:



RED A
RED 2

RED 3
RED 4
RED 5

RED 6
RED 7
RED 8
RED 9
RED 10
RED J

RED Q

RED K


I get an error. I guess the newlines in between are causing the problem.
Is there anyway to improve my Code?










share|improve this question







New contributor




momonosuke is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.











closed as off-topic by Sᴀᴍ Onᴇᴌᴀ, vnp, Zeta, Vogel612 Dec 22 at 12:16


This question appears to be off-topic. The users who voted to close gave this specific reason:


  • "Code not implemented or not working as intended: Code Review is a community where programmers peer-review your working code to address issues such as security, maintainability, performance, and scalability. We require that the code be working correctly, to the best of the author's knowledge, before proceeding with a review." – Sᴀᴍ Onᴇᴌᴀ, vnp, Zeta, Vogel612

If this question can be reworded to fit the rules in the help center, please edit the question.









  • 1




    Welcome to Code Review. Unfortunately, this question does not match what this site is about. Code Review is about improving existing, working code. Code Review is not the site to ask for help in fixing or changing what your code does. Once the code does what you want, we would love to help you do the same thing in a cleaner way! Please see our help center for more information. That being said, if you're fine with a review of your current version that doesn't support newlines, edit your question to remove the broken example and state the input format. Thanks!
    – Zeta
    Dec 22 at 8:49














0












0








0







I wrote a Program that gets the input from a txt file and stores the input in an array.
After that I remove the spaces from each string so that it's easier for me to compare the string values in the array reds against the string value in the array string card.



The array red must contain all the elements of the array stringcard or else an error message will be printed. It doesn't matter if the elements in the input file are in order.



#include <stdio.h> 
#include <string.h>
#include <stdlib.h>
#define max 13
#define stringlength 8

//removes spaces
char * removechar(char str, int ch) {

char * cpos = str;

while ((cpos = strchr(cpos, ch))) {
strcpy(cpos, cpos + 1);
}
return str;
}

int all_match( char **table1, const char **table2, size_t t1size, size_t t2size)
{
for(size_t t1index = 0; t1index < t1size; t1index++)
{
int match = 0;
for(size_t t2index = 0; t2index < t2size; t2index++)
{
match = match || !strcmp(table1[t1index], table2[t2index]);
if(match) {
break;
}
}
if(!match){
printf("error");
return 0;
}
}
return 1;
}

int main(int argc, char ** argv) {

const char *stringcard = {
"REDAn",
"RED2n",
"RED3n",
"RED4n",
"RED5n",
"RED6n",
"RED7n",
"RED8n",
"RED9n",
"RED10n",
"REDJn",
"REDQn",
"REDKn",

};



char * reds[max];

int i;

FILE * file = argc > 1 ? fopen(argv[1], "r") : stdin;
if (file == NULL)
return 1;
if (argc != 2) {
printf("[ERR]");
return 0;
}

for (i = 0; i < max; i++) {

reds[i] = malloc(stringlength);
fgets(reds[i], stringlength, file);

}




for (i = 0; i < max; i++) {

printf("%s", reds[i]);

}

// removes spaces
for (i = 0; i < max; i++) {
removechar(reds[i], ' ');


}

for (i = 0; i < max; i++) {

printf("%s", reds[i]);

}


size_t size = sizeof(stringcard) / sizeof(stringcard[0]);
size_t size2 = sizeof(reds) / sizeof(reds[0]);

all_match(reds,stringcard,size,size2);

for (i = 0; i < max; i++) {

free(reds[i]);

}

return 0;

}


input:



RED A
RED 2
RED 3
RED 4
RED 5
RED 6
RED 7
RED 8
RED 9
RED 10
RED J
RED Q
RED K


This code works fine as long as the input-file looks like that.



If the input file looks like this:



RED A
RED 2

RED 3
RED 4
RED 5

RED 6
RED 7
RED 8
RED 9
RED 10
RED J

RED Q

RED K


I get an error. I guess the newlines in between are causing the problem.
Is there anyway to improve my Code?










share|improve this question







New contributor




momonosuke is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.











I wrote a Program that gets the input from a txt file and stores the input in an array.
After that I remove the spaces from each string so that it's easier for me to compare the string values in the array reds against the string value in the array string card.



The array red must contain all the elements of the array stringcard or else an error message will be printed. It doesn't matter if the elements in the input file are in order.



#include <stdio.h> 
#include <string.h>
#include <stdlib.h>
#define max 13
#define stringlength 8

//removes spaces
char * removechar(char str, int ch) {

char * cpos = str;

while ((cpos = strchr(cpos, ch))) {
strcpy(cpos, cpos + 1);
}
return str;
}

int all_match( char **table1, const char **table2, size_t t1size, size_t t2size)
{
for(size_t t1index = 0; t1index < t1size; t1index++)
{
int match = 0;
for(size_t t2index = 0; t2index < t2size; t2index++)
{
match = match || !strcmp(table1[t1index], table2[t2index]);
if(match) {
break;
}
}
if(!match){
printf("error");
return 0;
}
}
return 1;
}

int main(int argc, char ** argv) {

const char *stringcard = {
"REDAn",
"RED2n",
"RED3n",
"RED4n",
"RED5n",
"RED6n",
"RED7n",
"RED8n",
"RED9n",
"RED10n",
"REDJn",
"REDQn",
"REDKn",

};



char * reds[max];

int i;

FILE * file = argc > 1 ? fopen(argv[1], "r") : stdin;
if (file == NULL)
return 1;
if (argc != 2) {
printf("[ERR]");
return 0;
}

for (i = 0; i < max; i++) {

reds[i] = malloc(stringlength);
fgets(reds[i], stringlength, file);

}




for (i = 0; i < max; i++) {

printf("%s", reds[i]);

}

// removes spaces
for (i = 0; i < max; i++) {
removechar(reds[i], ' ');


}

for (i = 0; i < max; i++) {

printf("%s", reds[i]);

}


size_t size = sizeof(stringcard) / sizeof(stringcard[0]);
size_t size2 = sizeof(reds) / sizeof(reds[0]);

all_match(reds,stringcard,size,size2);

for (i = 0; i < max; i++) {

free(reds[i]);

}

return 0;

}


input:



RED A
RED 2
RED 3
RED 4
RED 5
RED 6
RED 7
RED 8
RED 9
RED 10
RED J
RED Q
RED K


This code works fine as long as the input-file looks like that.



If the input file looks like this:



RED A
RED 2

RED 3
RED 4
RED 5

RED 6
RED 7
RED 8
RED 9
RED 10
RED J

RED Q

RED K


I get an error. I guess the newlines in between are causing the problem.
Is there anyway to improve my Code?







c strings array






share|improve this question







New contributor




momonosuke is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.











share|improve this question







New contributor




momonosuke is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.









share|improve this question




share|improve this question






New contributor




momonosuke is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.









asked Dec 21 at 23:55









momonosuke

1




1




New contributor




momonosuke is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.





New contributor





momonosuke is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.






momonosuke is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.




closed as off-topic by Sᴀᴍ Onᴇᴌᴀ, vnp, Zeta, Vogel612 Dec 22 at 12:16


This question appears to be off-topic. The users who voted to close gave this specific reason:


  • "Code not implemented or not working as intended: Code Review is a community where programmers peer-review your working code to address issues such as security, maintainability, performance, and scalability. We require that the code be working correctly, to the best of the author's knowledge, before proceeding with a review." – Sᴀᴍ Onᴇᴌᴀ, vnp, Zeta, Vogel612

If this question can be reworded to fit the rules in the help center, please edit the question.




closed as off-topic by Sᴀᴍ Onᴇᴌᴀ, vnp, Zeta, Vogel612 Dec 22 at 12:16


This question appears to be off-topic. The users who voted to close gave this specific reason:


  • "Code not implemented or not working as intended: Code Review is a community where programmers peer-review your working code to address issues such as security, maintainability, performance, and scalability. We require that the code be working correctly, to the best of the author's knowledge, before proceeding with a review." – Sᴀᴍ Onᴇᴌᴀ, vnp, Zeta, Vogel612

If this question can be reworded to fit the rules in the help center, please edit the question.








  • 1




    Welcome to Code Review. Unfortunately, this question does not match what this site is about. Code Review is about improving existing, working code. Code Review is not the site to ask for help in fixing or changing what your code does. Once the code does what you want, we would love to help you do the same thing in a cleaner way! Please see our help center for more information. That being said, if you're fine with a review of your current version that doesn't support newlines, edit your question to remove the broken example and state the input format. Thanks!
    – Zeta
    Dec 22 at 8:49














  • 1




    Welcome to Code Review. Unfortunately, this question does not match what this site is about. Code Review is about improving existing, working code. Code Review is not the site to ask for help in fixing or changing what your code does. Once the code does what you want, we would love to help you do the same thing in a cleaner way! Please see our help center for more information. That being said, if you're fine with a review of your current version that doesn't support newlines, edit your question to remove the broken example and state the input format. Thanks!
    – Zeta
    Dec 22 at 8:49








1




1




Welcome to Code Review. Unfortunately, this question does not match what this site is about. Code Review is about improving existing, working code. Code Review is not the site to ask for help in fixing or changing what your code does. Once the code does what you want, we would love to help you do the same thing in a cleaner way! Please see our help center for more information. That being said, if you're fine with a review of your current version that doesn't support newlines, edit your question to remove the broken example and state the input format. Thanks!
– Zeta
Dec 22 at 8:49




Welcome to Code Review. Unfortunately, this question does not match what this site is about. Code Review is about improving existing, working code. Code Review is not the site to ask for help in fixing or changing what your code does. Once the code does what you want, we would love to help you do the same thing in a cleaner way! Please see our help center for more information. That being said, if you're fine with a review of your current version that doesn't support newlines, edit your question to remove the broken example and state the input format. Thanks!
– Zeta
Dec 22 at 8:49










1 Answer
1






active

oldest

votes


















0














Undefined behavior



removechar() has problems.



//removes spaces
char * removechar(char str, int ch) {
char * cpos = str;
while ((cpos = strchr(cpos, ch))) {
strcpy(cpos, cpos + 1);
}
return str;
}



  • It is undefined behavior (UB) to call strcpy() with overlapping strings.


  • Inefficient. It algorithm is O(n*n). A string of 100 spaces would take an order of 10,000 operations.


  • Comment //removes spaces mis-leads. There is nothing about the function related to a "space", just the attempted removal of some ch which may or may not be a ' '.


  • Should code unusually call removechar(str, '') occur, cpos + 1 will point to 1 past the end of the string causing various troubles (UB).



To properly remove matching characters:



char *removechar(char str, int ch) {
if (ch) { // if ch == null character, detect that and do not change anything.
const char *src = str;

// Optional speedier initial loop should leading characters not contain `ch`
while (*src && ((unsigned char) *src != (unsigned char) ch)) {
src++;
}

char *dst = str;
while (*src) {
if ((unsigned char) *src != (unsigned char) ch) {
*dst++ = *src;
}
src++;
}
*dst = '';
}
return str;
}




Note: improved code uses casts in if ((unsigned char) *src != (unsigned char) ch) to cope with ch < 0 or ch > CHAR_MAX and/or char is signed. In such cases the compare intended is likely just the lower bits of *src and ch. strchr(s, c) compares using (unsigned char)*s == (unsigned char). We do likewise.



Alternatively, code could change the signature and drop the casts.



char *removechar(char str, char ch)




Vertical whitespace



For my tastes the vertical spacing is excessive and would benefit with a tidier appearance.



General formatting is weak. Use an auto formatting. Do not fix this manually.





Missing error checking



I'd expect fgets() calls to have their return value checked.



Robust code will check the return value of *alloc()





Error detection sequence



If argc < 2 then fopen(argv[1], "r") is UB. Better to check if (argc != 2) before.



 if (argc != 2) {
printf("[ERR]");
return 0;
}
FILE * file = argc > 1 ? fopen(argv[1], "r") : stdin;
if (file == NULL)
return 1;
//if (argc != 2) {
// printf("[ERR]");
// return 0;
//}


Better for error messages go to stderr.



When file open fails, no message. Consider adding one.






share|improve this answer























  • Thank you for your answer. I changed my Code the way you told me to. But now the function int all match gives me an error even though the input files are correct. The input file with no new lines in between gives me an error. And the input file with many new lines gives me an error aswell.
    – momonosuke
    Dec 22 at 8:05










  • Review int all_match( char **table1, const char **table2, size_t t1size, size_t t2size) { ... size_t size = sizeof(stringcard) / sizeof(stringcard[0]); size_t size2 = sizeof(reds) / sizeof(reds[0]); all_match(reds,stringcard,size,size2); to spot a problem.
    – chux
    Dec 22 at 12:11


















1 Answer
1






active

oldest

votes








1 Answer
1






active

oldest

votes









active

oldest

votes






active

oldest

votes









0














Undefined behavior



removechar() has problems.



//removes spaces
char * removechar(char str, int ch) {
char * cpos = str;
while ((cpos = strchr(cpos, ch))) {
strcpy(cpos, cpos + 1);
}
return str;
}



  • It is undefined behavior (UB) to call strcpy() with overlapping strings.


  • Inefficient. It algorithm is O(n*n). A string of 100 spaces would take an order of 10,000 operations.


  • Comment //removes spaces mis-leads. There is nothing about the function related to a "space", just the attempted removal of some ch which may or may not be a ' '.


  • Should code unusually call removechar(str, '') occur, cpos + 1 will point to 1 past the end of the string causing various troubles (UB).



To properly remove matching characters:



char *removechar(char str, int ch) {
if (ch) { // if ch == null character, detect that and do not change anything.
const char *src = str;

// Optional speedier initial loop should leading characters not contain `ch`
while (*src && ((unsigned char) *src != (unsigned char) ch)) {
src++;
}

char *dst = str;
while (*src) {
if ((unsigned char) *src != (unsigned char) ch) {
*dst++ = *src;
}
src++;
}
*dst = '';
}
return str;
}




Note: improved code uses casts in if ((unsigned char) *src != (unsigned char) ch) to cope with ch < 0 or ch > CHAR_MAX and/or char is signed. In such cases the compare intended is likely just the lower bits of *src and ch. strchr(s, c) compares using (unsigned char)*s == (unsigned char). We do likewise.



Alternatively, code could change the signature and drop the casts.



char *removechar(char str, char ch)




Vertical whitespace



For my tastes the vertical spacing is excessive and would benefit with a tidier appearance.



General formatting is weak. Use an auto formatting. Do not fix this manually.





Missing error checking



I'd expect fgets() calls to have their return value checked.



Robust code will check the return value of *alloc()





Error detection sequence



If argc < 2 then fopen(argv[1], "r") is UB. Better to check if (argc != 2) before.



 if (argc != 2) {
printf("[ERR]");
return 0;
}
FILE * file = argc > 1 ? fopen(argv[1], "r") : stdin;
if (file == NULL)
return 1;
//if (argc != 2) {
// printf("[ERR]");
// return 0;
//}


Better for error messages go to stderr.



When file open fails, no message. Consider adding one.






share|improve this answer























  • Thank you for your answer. I changed my Code the way you told me to. But now the function int all match gives me an error even though the input files are correct. The input file with no new lines in between gives me an error. And the input file with many new lines gives me an error aswell.
    – momonosuke
    Dec 22 at 8:05










  • Review int all_match( char **table1, const char **table2, size_t t1size, size_t t2size) { ... size_t size = sizeof(stringcard) / sizeof(stringcard[0]); size_t size2 = sizeof(reds) / sizeof(reds[0]); all_match(reds,stringcard,size,size2); to spot a problem.
    – chux
    Dec 22 at 12:11
















0














Undefined behavior



removechar() has problems.



//removes spaces
char * removechar(char str, int ch) {
char * cpos = str;
while ((cpos = strchr(cpos, ch))) {
strcpy(cpos, cpos + 1);
}
return str;
}



  • It is undefined behavior (UB) to call strcpy() with overlapping strings.


  • Inefficient. It algorithm is O(n*n). A string of 100 spaces would take an order of 10,000 operations.


  • Comment //removes spaces mis-leads. There is nothing about the function related to a "space", just the attempted removal of some ch which may or may not be a ' '.


  • Should code unusually call removechar(str, '') occur, cpos + 1 will point to 1 past the end of the string causing various troubles (UB).



To properly remove matching characters:



char *removechar(char str, int ch) {
if (ch) { // if ch == null character, detect that and do not change anything.
const char *src = str;

// Optional speedier initial loop should leading characters not contain `ch`
while (*src && ((unsigned char) *src != (unsigned char) ch)) {
src++;
}

char *dst = str;
while (*src) {
if ((unsigned char) *src != (unsigned char) ch) {
*dst++ = *src;
}
src++;
}
*dst = '';
}
return str;
}




Note: improved code uses casts in if ((unsigned char) *src != (unsigned char) ch) to cope with ch < 0 or ch > CHAR_MAX and/or char is signed. In such cases the compare intended is likely just the lower bits of *src and ch. strchr(s, c) compares using (unsigned char)*s == (unsigned char). We do likewise.



Alternatively, code could change the signature and drop the casts.



char *removechar(char str, char ch)




Vertical whitespace



For my tastes the vertical spacing is excessive and would benefit with a tidier appearance.



General formatting is weak. Use an auto formatting. Do not fix this manually.





Missing error checking



I'd expect fgets() calls to have their return value checked.



Robust code will check the return value of *alloc()





Error detection sequence



If argc < 2 then fopen(argv[1], "r") is UB. Better to check if (argc != 2) before.



 if (argc != 2) {
printf("[ERR]");
return 0;
}
FILE * file = argc > 1 ? fopen(argv[1], "r") : stdin;
if (file == NULL)
return 1;
//if (argc != 2) {
// printf("[ERR]");
// return 0;
//}


Better for error messages go to stderr.



When file open fails, no message. Consider adding one.






share|improve this answer























  • Thank you for your answer. I changed my Code the way you told me to. But now the function int all match gives me an error even though the input files are correct. The input file with no new lines in between gives me an error. And the input file with many new lines gives me an error aswell.
    – momonosuke
    Dec 22 at 8:05










  • Review int all_match( char **table1, const char **table2, size_t t1size, size_t t2size) { ... size_t size = sizeof(stringcard) / sizeof(stringcard[0]); size_t size2 = sizeof(reds) / sizeof(reds[0]); all_match(reds,stringcard,size,size2); to spot a problem.
    – chux
    Dec 22 at 12:11














0












0








0






Undefined behavior



removechar() has problems.



//removes spaces
char * removechar(char str, int ch) {
char * cpos = str;
while ((cpos = strchr(cpos, ch))) {
strcpy(cpos, cpos + 1);
}
return str;
}



  • It is undefined behavior (UB) to call strcpy() with overlapping strings.


  • Inefficient. It algorithm is O(n*n). A string of 100 spaces would take an order of 10,000 operations.


  • Comment //removes spaces mis-leads. There is nothing about the function related to a "space", just the attempted removal of some ch which may or may not be a ' '.


  • Should code unusually call removechar(str, '') occur, cpos + 1 will point to 1 past the end of the string causing various troubles (UB).



To properly remove matching characters:



char *removechar(char str, int ch) {
if (ch) { // if ch == null character, detect that and do not change anything.
const char *src = str;

// Optional speedier initial loop should leading characters not contain `ch`
while (*src && ((unsigned char) *src != (unsigned char) ch)) {
src++;
}

char *dst = str;
while (*src) {
if ((unsigned char) *src != (unsigned char) ch) {
*dst++ = *src;
}
src++;
}
*dst = '';
}
return str;
}




Note: improved code uses casts in if ((unsigned char) *src != (unsigned char) ch) to cope with ch < 0 or ch > CHAR_MAX and/or char is signed. In such cases the compare intended is likely just the lower bits of *src and ch. strchr(s, c) compares using (unsigned char)*s == (unsigned char). We do likewise.



Alternatively, code could change the signature and drop the casts.



char *removechar(char str, char ch)




Vertical whitespace



For my tastes the vertical spacing is excessive and would benefit with a tidier appearance.



General formatting is weak. Use an auto formatting. Do not fix this manually.





Missing error checking



I'd expect fgets() calls to have their return value checked.



Robust code will check the return value of *alloc()





Error detection sequence



If argc < 2 then fopen(argv[1], "r") is UB. Better to check if (argc != 2) before.



 if (argc != 2) {
printf("[ERR]");
return 0;
}
FILE * file = argc > 1 ? fopen(argv[1], "r") : stdin;
if (file == NULL)
return 1;
//if (argc != 2) {
// printf("[ERR]");
// return 0;
//}


Better for error messages go to stderr.



When file open fails, no message. Consider adding one.






share|improve this answer














Undefined behavior



removechar() has problems.



//removes spaces
char * removechar(char str, int ch) {
char * cpos = str;
while ((cpos = strchr(cpos, ch))) {
strcpy(cpos, cpos + 1);
}
return str;
}



  • It is undefined behavior (UB) to call strcpy() with overlapping strings.


  • Inefficient. It algorithm is O(n*n). A string of 100 spaces would take an order of 10,000 operations.


  • Comment //removes spaces mis-leads. There is nothing about the function related to a "space", just the attempted removal of some ch which may or may not be a ' '.


  • Should code unusually call removechar(str, '') occur, cpos + 1 will point to 1 past the end of the string causing various troubles (UB).



To properly remove matching characters:



char *removechar(char str, int ch) {
if (ch) { // if ch == null character, detect that and do not change anything.
const char *src = str;

// Optional speedier initial loop should leading characters not contain `ch`
while (*src && ((unsigned char) *src != (unsigned char) ch)) {
src++;
}

char *dst = str;
while (*src) {
if ((unsigned char) *src != (unsigned char) ch) {
*dst++ = *src;
}
src++;
}
*dst = '';
}
return str;
}




Note: improved code uses casts in if ((unsigned char) *src != (unsigned char) ch) to cope with ch < 0 or ch > CHAR_MAX and/or char is signed. In such cases the compare intended is likely just the lower bits of *src and ch. strchr(s, c) compares using (unsigned char)*s == (unsigned char). We do likewise.



Alternatively, code could change the signature and drop the casts.



char *removechar(char str, char ch)




Vertical whitespace



For my tastes the vertical spacing is excessive and would benefit with a tidier appearance.



General formatting is weak. Use an auto formatting. Do not fix this manually.





Missing error checking



I'd expect fgets() calls to have their return value checked.



Robust code will check the return value of *alloc()





Error detection sequence



If argc < 2 then fopen(argv[1], "r") is UB. Better to check if (argc != 2) before.



 if (argc != 2) {
printf("[ERR]");
return 0;
}
FILE * file = argc > 1 ? fopen(argv[1], "r") : stdin;
if (file == NULL)
return 1;
//if (argc != 2) {
// printf("[ERR]");
// return 0;
//}


Better for error messages go to stderr.



When file open fails, no message. Consider adding one.







share|improve this answer














share|improve this answer



share|improve this answer








edited Dec 22 at 2:25

























answered Dec 22 at 1:45









chux

12.6k11344




12.6k11344












  • Thank you for your answer. I changed my Code the way you told me to. But now the function int all match gives me an error even though the input files are correct. The input file with no new lines in between gives me an error. And the input file with many new lines gives me an error aswell.
    – momonosuke
    Dec 22 at 8:05










  • Review int all_match( char **table1, const char **table2, size_t t1size, size_t t2size) { ... size_t size = sizeof(stringcard) / sizeof(stringcard[0]); size_t size2 = sizeof(reds) / sizeof(reds[0]); all_match(reds,stringcard,size,size2); to spot a problem.
    – chux
    Dec 22 at 12:11


















  • Thank you for your answer. I changed my Code the way you told me to. But now the function int all match gives me an error even though the input files are correct. The input file with no new lines in between gives me an error. And the input file with many new lines gives me an error aswell.
    – momonosuke
    Dec 22 at 8:05










  • Review int all_match( char **table1, const char **table2, size_t t1size, size_t t2size) { ... size_t size = sizeof(stringcard) / sizeof(stringcard[0]); size_t size2 = sizeof(reds) / sizeof(reds[0]); all_match(reds,stringcard,size,size2); to spot a problem.
    – chux
    Dec 22 at 12:11
















Thank you for your answer. I changed my Code the way you told me to. But now the function int all match gives me an error even though the input files are correct. The input file with no new lines in between gives me an error. And the input file with many new lines gives me an error aswell.
– momonosuke
Dec 22 at 8:05




Thank you for your answer. I changed my Code the way you told me to. But now the function int all match gives me an error even though the input files are correct. The input file with no new lines in between gives me an error. And the input file with many new lines gives me an error aswell.
– momonosuke
Dec 22 at 8:05












Review int all_match( char **table1, const char **table2, size_t t1size, size_t t2size) { ... size_t size = sizeof(stringcard) / sizeof(stringcard[0]); size_t size2 = sizeof(reds) / sizeof(reds[0]); all_match(reds,stringcard,size,size2); to spot a problem.
– chux
Dec 22 at 12:11




Review int all_match( char **table1, const char **table2, size_t t1size, size_t t2size) { ... size_t size = sizeof(stringcard) / sizeof(stringcard[0]); size_t size2 = sizeof(reds) / sizeof(reds[0]); all_match(reds,stringcard,size,size2); to spot a problem.
– chux
Dec 22 at 12:11



Popular posts from this blog

Terni

A new problem with tex4ht and tikz

Sun Ra