-3

My code is here:

char* kropecka(char* tab)
{
    int a=0,b=0;
    char* zwr;
    zwr=(char*)malloc(30*sizeof(char));

    for(a;strlen(tab);a++)
    {
        if(tab[a]!='.')
        {
            if(isupper(tab[a]))
                zwr[b]=tolower(tab[a]);
            if(islower(tab[a]))
                zwr[b]=toupper(tab[a]);
            b++;
        }
    }
    zwr[b]='\0';
    return zwr;
}

There is no errors, warnings or something like this. But program crashed when I give him some string:

--------------------------- Microsoft Visual C++ Debug Library --------------------------- Debug Assertion Failed!

Program: ...s\Visual Studio 2010\Projects\C_homework\Debug\C_homework.exe File: f:\dd\vctools\crt_bld\self_x86\crt\src\isctype.c Line: 56

Expression: (unsigned)(c + 1) <= 256

For information on how your program can cause an assertion failure, see the Visual C++ documentation on asserts.

(Press Retry to debug the application)

--------------------------- Abort Retry Ignore

Compilator: Visual Studio 2010 Included libary: stdio.h, string.h, ctype.h, stdlib.h (for system() function in main() ).

Alexey Frunze
  • 61,140
  • 12
  • 83
  • 180
1_bug
  • 5,505
  • 4
  • 50
  • 58
  • execute tolower() next if(islower) match execute toupper(), use else – BLUEPIXY Apr 08 '13 at 10:46
  • In your "if (isupper()...; if (islower()...;" code, it appears you're trying to toggle the case, however this will always result in an upper case. You can turn it into a proper toggle by adding an `else` on the second `if`. – mah Apr 08 '13 at 10:50

4 Answers4

4

From the C standard:

The header <ctype.h> declares several functions useful for classifying and mapping characters. In all cases the argument is an int, the value of which shall be representable as an unsigned char or shall equal the value of the macro EOF. If the argument has any other value, the behavior is undefined.

Emphasis mine.

MSDN's description of toupper() hints at this as well:

In order for toupper to give the expected results, __isascii and isupper must both return nonzero.

isascii():

__isascii returns a nonzero value if c is an ASCII character (in the range 0x00 – 0x7F).

Alexey Frunze
  • 61,140
  • 12
  • 83
  • 180
3

The exit test for your loop is wrong. strlen(tab) will always return either false or true (depending on tab). This means that you continue writing to zwr beyond its allocated length. The effects of this are undefined but its not surprising that it eventually crashes.

You can fix this by changing the loop to

for(a;a<strlen(tab);a++)
//    ^^

Another possible cause of error is that zwr is hard-coded as 30 bytes. This clearly isn't sufficient for all possible values of tab so you could change the code to

size_t len = strlen(zwr)+1;
zwr=malloc(len);
for(;a<len;a++)
simonc
  • 41,632
  • 12
  • 85
  • 103
  • @mah I think I'm answering exactly the question that was asked. I've updated my answer to explain this more clearly. If you still disagree, can you explain why my answer is inappropriate please? – simonc Apr 08 '13 at 10:46
  • I agree. The lack of explanation made the answer seem orthagonal but this explanation is much more helpful. – mah Apr 08 '13 at 10:48
2

This will run forever:

for(a;strlen(tab);a++)

I think you meant:

for(a;a < strlen(tab);a++)

Or better (because strlen is O(n)):

for(;tab[a];a++)
Thomas
  • 174,939
  • 50
  • 355
  • 478
0

Check the callstack - hopefully it will take you to the root of the problem.

int __cdecl _chvalidator(
    int c,
    int mask
    )
 {
    _ASSERTE((unsigned)(c + 1) <= 256);
    return ( _pctype[c] & mask);
 }

This method looks like one that checks for character value bounds...

isctype.c -

/***
* __chvalidator
*
* Purpose:
*      This function is called by character testing functions in debug
*      versions. This function test for validation of c as character.
*      For improvement in performance, it is not used in non-debug
*      version.  It is available in the static single-thread non-debug
*      build, though, just in case C code that includes ctype.h is compiled
*      /D_DEBUG /ML.
*
*******************************************************************************/

In simple terms it seems that you are overflowing on a variable i.e. Unsigned Char can take a maximum value of 255. If you add 1 to an existing value of 255 - you overflow on it.

Hope it helps.

Hiren Pandya
  • 989
  • 1
  • 7
  • 20