C
craigbeanhead
Hi clc readers,
I'm working on a problem, and I've got some working code, but I think
it can be improved. In particular I'd like to get rid of the nasty
goto statement that I've used, but I'm unsure as to how to go about
rewriting that section.
The problem is to find a word of x length, where the sum of the
characters (using 1 for A, 2 for B, etc) is equal to y.
I'm calling the program like this: "myprog.exe 5 39" - this means
"find me all the words of length 5, where the characters add up to
39". I've got two solutions to the problem, one version creates
strings such as AAAAA, AAAAB, and the second version searches a
newline-delimited dictionary of words.
It seems that each time I post code here (or someone else posts code
here), it ends up being improved I hope someone here can help me
improve the code I've written so far.
Thanks,
Craig
Code follows:
/*Cut here*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#define MAX_LINE_LENGTH 100
int findstring(int nLength, int nSum, char* sFile);
int makewords(int nLength, int nSum);
char tochar(int i);
int tonum(char c);
int strsum(char* s);
void ucase(char *s);
int main(int argc, char *argv[])
{
int nLength, nSum, nMatches;
char *stop = NULL;
char** words = NULL;
if(argc!=3)
{
puts("Please supply two arguments, the word length, and the desired
sum of the characters");
exit(EXIT_FAILURE);
}
nLength = (int)strtol(argv[1], &stop, 10);
nSum = (int)strtol(argv[2], &stop, 10);
/* nMatches = makewords(nLength, nSum, words); */
nMatches = findstring(nLength, nSum, "dictionary.txt");
printf("%d matches found\n", nMatches);
exit(EXIT_SUCCESS);
}
int findstring(int nLength, int nSum, char* sFile)
{
FILE* fp = fopen(sFile, "r");
char line[MAX_LINE_LENGTH + 1];
int i = 0;
while(fgets(line, MAX_LINE_LENGTH, fp) != NULL)
{
line[strlen(line)-1] = '\0';
upper(line);
if(strlen(line) != nLength) continue;
/* printf("Sum of %s is %d, Aiming for %d\n", line, strsum(line),
nSum); */
if(strsum(line) != nSum) continue;
printf("%s\n", line);
i++;
}
fclose(fp);
return i;
}
int makewords(int nLength, int nSum)
{
char *chars = malloc(nLength+1);
int i,j=0;
/* reset the memory to all 'A's */
for(i = 0; i<nLength; i++)
chars = tochar(1);
chars[nLength] = '\0';
/* forever */
while(1)
{
int i;
/* test for string sum */
if(strsum(chars) == nSum)
{
printf("%s\n", chars);
j++;
}
chars[nLength-1]++;
start_again:
for(i=nLength-1; i>=0; i--)
if(tonum(chars) >= 27)
{
if(i==0) return 0;
chars = 'A';
chars[i-1]++;
goto start_again;
}
}
free(chars);
return j;
}
/* Takes 1, returns 'A', takes 2, returns 'B' */
char tochar(int i)
{
return 'A' + i - 1;
}
/* Takes 'A', returns 1, takes 'B', returns 2 */
int tonum(char c)
{
return c - 'A' + 1;
}
/* Takes "ABC", returns 1 + 2 + 3 = 6 */
int strsum(char *s)
{
int i=0;
char *c;
while(*(c = s++))
i += tonum(*c);
return i;
}
/* takes "a WordOrTwo", returns "A WORDORTWO" */
void ucase(char *s)
{
while(*s++ = toupper(*s))
;
}
I'm working on a problem, and I've got some working code, but I think
it can be improved. In particular I'd like to get rid of the nasty
goto statement that I've used, but I'm unsure as to how to go about
rewriting that section.
The problem is to find a word of x length, where the sum of the
characters (using 1 for A, 2 for B, etc) is equal to y.
I'm calling the program like this: "myprog.exe 5 39" - this means
"find me all the words of length 5, where the characters add up to
39". I've got two solutions to the problem, one version creates
strings such as AAAAA, AAAAB, and the second version searches a
newline-delimited dictionary of words.
It seems that each time I post code here (or someone else posts code
here), it ends up being improved I hope someone here can help me
improve the code I've written so far.
Thanks,
Craig
Code follows:
/*Cut here*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#define MAX_LINE_LENGTH 100
int findstring(int nLength, int nSum, char* sFile);
int makewords(int nLength, int nSum);
char tochar(int i);
int tonum(char c);
int strsum(char* s);
void ucase(char *s);
int main(int argc, char *argv[])
{
int nLength, nSum, nMatches;
char *stop = NULL;
char** words = NULL;
if(argc!=3)
{
puts("Please supply two arguments, the word length, and the desired
sum of the characters");
exit(EXIT_FAILURE);
}
nLength = (int)strtol(argv[1], &stop, 10);
nSum = (int)strtol(argv[2], &stop, 10);
/* nMatches = makewords(nLength, nSum, words); */
nMatches = findstring(nLength, nSum, "dictionary.txt");
printf("%d matches found\n", nMatches);
exit(EXIT_SUCCESS);
}
int findstring(int nLength, int nSum, char* sFile)
{
FILE* fp = fopen(sFile, "r");
char line[MAX_LINE_LENGTH + 1];
int i = 0;
while(fgets(line, MAX_LINE_LENGTH, fp) != NULL)
{
line[strlen(line)-1] = '\0';
upper(line);
if(strlen(line) != nLength) continue;
/* printf("Sum of %s is %d, Aiming for %d\n", line, strsum(line),
nSum); */
if(strsum(line) != nSum) continue;
printf("%s\n", line);
i++;
}
fclose(fp);
return i;
}
int makewords(int nLength, int nSum)
{
char *chars = malloc(nLength+1);
int i,j=0;
/* reset the memory to all 'A's */
for(i = 0; i<nLength; i++)
chars = tochar(1);
chars[nLength] = '\0';
/* forever */
while(1)
{
int i;
/* test for string sum */
if(strsum(chars) == nSum)
{
printf("%s\n", chars);
j++;
}
chars[nLength-1]++;
start_again:
for(i=nLength-1; i>=0; i--)
if(tonum(chars) >= 27)
{
if(i==0) return 0;
chars = 'A';
chars[i-1]++;
goto start_again;
}
}
free(chars);
return j;
}
/* Takes 1, returns 'A', takes 2, returns 'B' */
char tochar(int i)
{
return 'A' + i - 1;
}
/* Takes 'A', returns 1, takes 'B', returns 2 */
int tonum(char c)
{
return c - 'A' + 1;
}
/* Takes "ABC", returns 1 + 2 + 3 = 6 */
int strsum(char *s)
{
int i=0;
char *c;
while(*(c = s++))
i += tonum(*c);
return i;
}
/* takes "a WordOrTwo", returns "A WORDORTWO" */
void ucase(char *s)
{
while(*s++ = toupper(*s))
;
}