0

I've been staring at this code for quite awhile and I can't find out what's wrong with this code and how to fix it. I think one of the arrays is being written past whats been allocated.

The debugger is allowing me to compile, but when I do, I get:

Unhandled exception at 0x774615de in HW6_StringProcessing.exe: 0xC0000005: Access violation.

Here is the code:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_STR_SIZE 100

void convertToPigLatin (char * strPtr, char * pStrPtr);

int main(int argc, char *argv[])
{
   char str[MAX_STR_SIZE];
   char pStr[MAX_STR_SIZE];
   FILE *fileInPtr;                             //Create file name
   FILE *fileOutPtr;    

   fileInPtr = fopen("pigLatinIn.txt", "r");    //Assign text to file
   fileOutPtr = fopen("pigLatinOut.txt", "w");

   if(fileInPtr == NULL)                        //Check if file exists
   {
      printf("Failed");
      exit(-1); 
   }
   fprintf(fileOutPtr, "English Word\t\t\t\tPig Latin Word\n");
   fprintf(fileOutPtr, "---------------\t\t\t\t----------------\n");

   while(!feof(fileInPtr))                  //Cycles until end of text
   {

      fscanf(fileInPtr, "%99s", str);       //Assigns word to *char

      str[99] = '\0';                       //Optional: Whole line

      convertToPigLatin(str, pStr); 

      //fprintf(fileOutPtr, "%15s\t\t\t\t%15p\n", str, pStr); 

      printf("%s\n", str); 
   }  

   system("pause"); 
}

void convertToPigLatin (const char * strPtr, char * pStrPtr)
{
   int VowelDetect = 0; 
   int LoopCounter = 0; 
   int consonantCounter = 0; 
   char cStr[MAX_STR_SIZE] = {'\0'};
   char dStr[] = {'-','\0'}; 
   char ayStr[] = {'a','y','\0'};
   char wayStr[] = {'w','a','y','\0'};

   while (*strPtr != '\0')
   {
      if (*strPtr == 'a' || *strPtr == 'e' || 
          *strPtr == 'i' || *strPtr == 'o' || 
          *strPtr == 'u' || VowelDetect ==1)
      {
         strncat(pStrPtr, strPtr, 1); 
         VowelDetect = 1; 
      }
      else
      {
         strncat(cStr, strPtr, 1); 
         consonantCounter++; 
      }
      *strPtr++;
   }
   strcat(pStrPtr, dStr); 
   if (consonantCounter == 0)  
   {
      strcat(pStrPtr, wayStr);
   }
   else
   {
      strcat(cStr,ayStr);
      strcat(pStrPtr, cStr);
   }  
   printf("%s\n", pStrPtr);                         

}
3
  • and ... WHAT is the problem you are experiencing? Commented Jul 25, 2013 at 5:57
  • 1
    Where do you initialize pStrPtr? You use strncat on it... what was the value before? What is the value at the beginning of the function? Commented Jul 25, 2013 at 6:06
  • user2525288, what warnings do you get when you compile this? (You do have all the warnings turned on, right?) Commented Jul 25, 2013 at 6:25

4 Answers 4

1

I think the issue might be the use of strcat() and strncat() to a buffer which hasn't been initialised. Before calling convertToPigLatin(), ensure you blat pStr[] with memset() or some such:

while(!feof(fileInPtr)) {
    ...
    str[99] = '\0';
    pStr[0] = '\0';    // or memset(pStr, 0, sizeof(pStr));
    convertToPigLatin(str, pStr);
    ...
}
Sign up to request clarification or add additional context in comments.

6 Comments

Hm. Why is pStr set with only [0]? shouldn't I give it larger of a memory allocation?
That's not an allocation. It's an initialization. You're setting the first byte to null, so string-handling functions see it as a zero-length string.
got it. i handled it with something similar in initialization: char pStr[MAX_STR_SIZE] = {'\0'};. I think I've narrowed the problem down to the fact that when convertToPigLatin reiterates several times, the pStrPtr has advanced from its original location. This means that the array soon fills up and then starts writing past its allocation. How can I make sure that every time the while loop iterates that pStr and pStrPtr (that is created by the function itself) point to the very first location in memory?
@user2525288 My answer provides your, er, answer. You need to re-init the array within the while loop.
@user2525288 I have updated the answer to show this more clearly.
|
0

The decleration:

void convertToPigLatin (char * strPtr, char * pStrPtr);

is not consistent with the definition of the function:

void convertToPigLatin (const char * strPtr, char * pStrPtr)
{
   ...                       
}

2 Comments

Good catch, but that wasn't it unfortunately. I'm still getting the "Unhandled exception at 0x774615de in HW6_StringProcessing.exe: 0xC0000005: Access violation."
@user2525288 If the compilation is OK, then just use the debugger to find out where you get the Access violation exception. I do not have your data.
0

Prototype is:

void convertToPigLatin (char * strPtr, char * pStrPtr);

but this function expects const char *

void convertToPigLatin (const char * strPtr, char * pStrPtr)

----------------------------------------^ here

Also, you have to increment the pointer itself (not the value) of strPtr in convertToPigLatin

*strPtr++;

should be:

strPtr++;

Comments

0

Here's an annotated, working version with some changes and suggestions. You'll probably want to toss the final printf, but I wanted to make sure there was visible output on the first run. The intent here is to stay close to the question's actual code, not to rewrite it entirely.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define XSTR(n) #n // a hack to allow stringify to use the *value of a macro
#define STR(n) XSTR(n)
#define MAX_STR_SIZE 100

void convertToPigLatin (const char * strPtr, char * pStrPtr);

int main(int argc, char *argv[])
{
    // The str and pStr aren't very meaningful, I'd suggent eng and pig.
    // Adding -"Str" to all your strings just slows down reading.
    // - plus it makes "str" an anomaly.
    char str[MAX_STR_SIZE + 1];   // +1 since NUL is usually not counted..
    char pStr[MAX_STR_SIZE + 1];  // ...by functions like strlen().  
    FILE *fileInPtr  = fopen("pigLatinIn.txt", "r");    //Assign text to file
    FILE *fileOutPtr = fopen("pigLatinOut.txt", "w");
    const char *fmt = "%15s     %s\n"; // for head and table output.
    if( ! (fileInPtr && fileOutPtr)) {
        perror("unable to open file(s) for I/O")
        return -1;
    }
    fprintf(fileOutPtr, fmt, "English Word", "Pig Latin Word");
    fprintf(fileOutPtr, fmt, "------------", "---------------");

    // put test before fscanf so we don't lose the last input line on EOF
    while(!feof(fileInPtr))           //Cycles until end of text
    {
        if(1 == fscanf(fileInPtr, "%" STR(MAX_STR_SIZE) "s", str))
        {
            str[MAX_STR_SIZE] = '\0';      //Optional: Whole line
            convertToPigLatin(str, pStr); 
            fprintf(fileOutPtr, fmt, str, pStr);
        }
        // else fprintf(stderr, "skipping empty line\n");  // for example.
    }  
    // system("pause") would be... icky, sleep(...) or 
    // getchar() are better, but still odd since output is going
    // to a file
    fclose(fileInPtr);
    fclose(fileOutPtr);
    return 0;           // a zero exit status from main() means success :-)
}

void convertToPigLatin (const char * strPtr, char * pStrPtr)
{
    int VowelDetected = 0;
    int LoopCounter = 0; 
    int ConsonantCounter = 0; 
    char cStr[MAX_STR_SIZE + 1] = {'\0'};
    char dStr[]   = "-";    // same as {'-','\0'}; 
    char ayStr[]  = "ay";   // same as {'a','y','\0'};
    char wayStr[] = "way";  // same as {'w','a','y','\0'};

    pStrPtr[0] = '\0';      // clear out pStr so trash doesn't prefix output.

    // a better loop control would be:  for( /*prior*/ ; *strPtr ; ++strPtr)
    //  - which lets you move the strPtr++ to the top line of the for loop.
    while (*strPtr != '\0')    // could simplify to:  while(*strPtr)
    {
#if 0   // disabling this to show a different option in the #else clause
        if (   *strPtr == 'a'
            || *strPtr == 'e'
            || *strPtr == 'i'
            || *strPtr == 'o'
            || *strPtr == 'u'
            || VowelDetected == 1)
        {
#else
        if (strchr("aeiou", *strPtr) || VowelDetected == 1)
        {
#endif
            strncat(pStrPtr, strPtr, 1); 
            VowelDetected = 1; 
        }
        else
        {
            strncat(cStr, strPtr, 1); 
            ConsonantCounter++; 
        }
        ++strPtr;   // a *strPtr++ would increment the target char itself.
    }
    strcat(pStrPtr, dStr);
    if (ConsonantCounter == 0)     // or: if( ! Consonantcounter)
    {
        strcat(pStrPtr, wayStr);
    }
    else
    {
        strcat(cStr,ayStr);
        strcat(pStrPtr, cStr);
    }  

    printf("# %s\n", pStrPtr);
}

2 Comments

There is a resource leak (fileOutPtr) in the "main" function. "fclose(fileOutPtr)" should be added before the function return. Can I fix it?
Go for it, @HengLi - although both file pointers should be checked (and later closed) :-)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.