Segmentation faulting in assignment
I'm currently learning C and I came from java. Our assignment asked us to count strings from either a file that could be added or it asks for the user to input a string. We just started using pointers and i looked up the different reasons why segmentation faults happened but I have no idea how to check for which issue it is. I initialized all my pointers to NULL but it still didn't work and from what i read that was the most common reason why a segmentation fault happens.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int debug = 0;
int
main(int argc, char **argv)
{
extern char *optarg;
extern int optind;
FILE* infile = NULL;
int c, err = 0;
int lflag = 0, sflag = 0, count = 0; //flags and count
char *shortWord = NULL, *longWord = NULL; //variable for shortest and longest word
int shortest = 100, longest = 0; //longest char 100, shortest 0
char *string = NULL;
char *pch = NULL;
static char usage[] = "usage: %s [-l] [-s] [filename]n";
while ((c = getopt(argc, argv, "ls")) != -1)
switch (c)
{
case 'l':
lflag = 1;
break;
case 's':
sflag = 1;
break;
case '?':
err = 1;
break;
}
if (err)
{
fprintf(stderr, usage, argv[0]);
exit(1);
}
//checks for file and then runs loop for word count
infile = fopen("myfile.txt","r");
if (infile != NULL)
{
fgets(string, 100, infile);
pch = strtok (string, " ,.-");
while(pch != NULL)
{
count++;
if (strlen(pch) > longest)
longWord = pch;
if (strlen(pch) < shortest)
shortWord = pch;
pch = strtok (NULL, " ,.");
}
}
//else, asks for string
else
{
printf("Enter your string: n");
fgets(string, 100, stdin);
int len = strlen(string);
count = len;
pch = strtok ( string, " ,.-");
while(pch != NULL)
{
count++;
if (strlen(pch) > longest)
longWord = pch;
if (strlen(pch) < shortest)
shortWord = pch;
pch = strtok (NULL, " ,.");
}
}
//following lines compute value based on arguments
if(lflag == 1)
{
printf("Longest word is %s", longWord);
}
if(sflag == 1)
{
printf("Shortest word is %s", shortWord);
}
printf("Word count = %.2dn", count);
exit(0);
}
Their are some issues in your code:
string
to NULL
, then used it as an input buffer for fgets()
. fgets()
reqiures a pointer to an array of chars, either declared on the stack or dynamically allocated with malloc(3)
. You can set an input buffer such as char string[100]
. fgets()
must be checked, as it returns NULL
when unable to read a line. strtok()
is not accounting for the n
character appended by fgets()
. You can either remove this newline, or include it in the delimter. If you want to include it in the delimeter, make sure your delimiter is " ,.-n"
. strtok()
, as this would allow your main()
to be shorter and reduce the repetitiveness in the code. An example function prototype could be void longest_shortest_words(char line[], char **longest, char **shortest, size_t *word_count);
, whereby you pass the longest, shortest words along with the number of words back to main()
via pointers. You could also just store the longest and shortest words in a 2D array or array of pointers. You should also explicitly check that your file was opened correctly. Something like this should be included:
infile = fopen("myfile.txt", "r");
if (infile == NULL) {
fprintf(stderr, "Failed to open filen");
exit(EXIT_FAILURE);
}
When checking opt
, checking ?
as a character in your switch statement is not right. Instead of:
case '?':
err = 1;
break;
Use default
, which covers any other invalid option entered. Here is how you can use it:
default:
fprintf(stderr, "usage: %s [-l] [-s] [filename]n", argv[0]);
exit(EXIT_FAILURE);
Checking sflag
and lflag
at the end is not enough. You should check if longWord
and shortWord
are not NULL
.
Here is some example code which demonstrates these points:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#define LINESIZE 100
void longest_shortest_words(char line[], char **longest, char **shortest, size_t *wordcount);
void print_output(int lflag, int sflag, char *longword, char *shortword, size_t wordcount);
void remove_newline(char line[]);
int main(int argc, char * const argv[]) {
FILE *infile;
char line[LINESIZE] = {' '};
int opt, sflag = 0, lflag = 0;
size_t wordcount = 0;
const char *optstr = "ls";
char *longword = NULL, *shortword = NULL;
while ((opt = getopt(argc, argv, optstr)) != -1) {
switch(opt) {
case 'l':
lflag = 1;
break;
case 's':
sflag = 1;
break;
default:
fprintf(stderr, "usage: %s [-l] [-s] [filename]n", argv[0]);
exit(EXIT_FAILURE);
}
}
/* Checking if file is in directory */
infile = fopen("myfile.txt", "r");
if (infile == NULL) {
fprintf(stderr, "Failed to open filen");
exit(EXIT_FAILURE);
}
/* checking if line exists in file */
if (fgets(line, LINESIZE, infile) == NULL) {
fprintf(stderr, "No line found in file.n");
printf("nEnter string instead:n");
if (fgets(line, LINESIZE, stdin) != NULL) {
remove_newline(line);
longest_shortest_words(line, &longword, &shortword, &wordcount);
/* checking that longWord, shortWord and word_count are valid */
if (longword != NULL && shortword != NULL && wordcount > 0) {
print_output(lflag, sflag, longword, shortword, wordcount);
}
}
/* file has line, do stuff with it */
} else {
remove_newline(line);
longest_shortest_words(line, &longword, &shortword, &wordcount);
print_output(lflag, sflag, longword, shortword, wordcount);
}
exit(EXIT_SUCCESS);
}
/* function for printing output, can be improved */
void print_output(int lflag, int sflag, char *longword, char *shortword, size_t wordcount) {
if (lflag) {
printf("Longest word: %sn", longword);
}
if (sflag) {
printf("Shortest word: %sn", shortword);
}
if (wordcount > 0) {
printf("Word count = %zun", wordcount);
}
}
/* function for removing newline, and checking that input hasnt exceeded limit */
void remove_newline(char line[]) {
size_t slen;
slen = strlen(line);
if (slen > 0 && line[slen-1] == 'n') {
line[slen-1] = ' ';
} else {
fprintf(stderr, "nToo many characters in input.n");
exit(EXIT_FAILURE);
}
}
/* function which parses line, and saves longWord and shortWord in pointers */
void longest_shortest_words(char line[], char **longword, char **shortword, size_t *wordcount) {
char *word = NULL;
const char *delim = " ,.";
word = strtok(line, delim);
if (word != NULL) {
*longword = word;
*shortword = word;
*wordcount = 1;
}
while ((word = strtok(NULL, delim)) != NULL) {
(*wordcount)++;
if (strlen(word) > strlen(*longword)) {
*longword = word;
} else if (strlen(word) < strlen(*shortword)) {
*shortword = word;
}
}
}
Note: The code shown above can be improved, it is just to show you another approach to your problem.
链接地址: http://www.djcxy.com/p/43900.html上一篇: malloc()和free()如何工作?
下一篇: 分配错误分配