Program that checks if an array contains all the elements it's supposed to contain [closed]
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
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.
add a comment |
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
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
add a comment |
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
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
c strings array
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.
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
add a comment |
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
add a comment |
1 Answer
1
active
oldest
votes
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 spacesmis-leads. There is nothing about the function related to a "space", just the attempted removal of somechwhich may or may not be a' '.Should code unusually call
removechar(str, '')occur,cpos + 1will 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.
Thank you for your answer. I changed my Code the way you told me to. But now the functionint all matchgives 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
Reviewint 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
add a comment |
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
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 spacesmis-leads. There is nothing about the function related to a "space", just the attempted removal of somechwhich may or may not be a' '.Should code unusually call
removechar(str, '')occur,cpos + 1will 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.
Thank you for your answer. I changed my Code the way you told me to. But now the functionint all matchgives 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
Reviewint 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
add a comment |
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 spacesmis-leads. There is nothing about the function related to a "space", just the attempted removal of somechwhich may or may not be a' '.Should code unusually call
removechar(str, '')occur,cpos + 1will 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.
Thank you for your answer. I changed my Code the way you told me to. But now the functionint all matchgives 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
Reviewint 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
add a comment |
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 spacesmis-leads. There is nothing about the function related to a "space", just the attempted removal of somechwhich may or may not be a' '.Should code unusually call
removechar(str, '')occur,cpos + 1will 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.
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 spacesmis-leads. There is nothing about the function related to a "space", just the attempted removal of somechwhich may or may not be a' '.Should code unusually call
removechar(str, '')occur,cpos + 1will 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.
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 functionint all matchgives 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
Reviewint 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
add a comment |
Thank you for your answer. I changed my Code the way you told me to. But now the functionint all matchgives 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
Reviewint 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
add a comment |
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