0

I have noticed that when I don't initialize the array in this code that turns lowercase to uppercase the code only does half of the work (it turns Antoine Copepe -> aNTOiNE_cOPEPE). I was wondering if there were the null reference errors Kevin was talking about in his answer to how much important it is to initialize arrays

#include <iostream>
#include<string.h>
#include<ctype.h>
#include<conio.h>

using namespace std;

void ConvMl_(char [], int);

int main(){
    char Nombre[32];
    int Len;
    
    cout<< "inserte su nombre completo: ";
    cin.getline(Nombre,32);
    
    Len = strlen(Nombre);
    
    ConvMl_(Nombre, Len);
    
    cout<<Nombre<<endl;
    
    getch();
    return 0;
}

void ConvMl_(char Nombre[], int Len){
    int Arr[Len] = { 'EsNecesarioInicializarElArray' };
    
    for(int i=0;i<Len;i++){
        if(Nombre[i] == ' '){
            Nombre[i] = '_';
        }   
    }
    
    for(int i=0;i<Len;i++){
        if(Nombre[i] >= 'A' && Nombre[i] <= 'Z'){
            Nombre[i] = tolower(Nombre[i]);
            Arr[i]=1;
        }
    }
    
    for(int i=0;i<Len;i++){
        if(Nombre[i] >= 'a' && Nombre[i] <= 'z' && Arr[i] != 1){
            Nombre[i] = toupper(Nombre[i]);
        }
    }
}

Indeed this gives me:

main.cpp:28:22: warning: character constant too long for its type                                                             
inserte su nombre completo: Antoine Coppepe                                                                                   
aNTOINE_cOPPEPE

Whereas when I do int Arr[Len]; I only have Antoine Copepe -> aNTOiNE_cOPEPE

Revolucion for Monica
  • 2,848
  • 8
  • 39
  • 78
  • `int Arr[] = { "EsNecesarioInicializarElArray" };` – Aykhan Hagverdili Mar 05 '21 at 14:46
  • 1
    [Why aren't variable-length arrays part of the C++ standard?](https://stackoverflow.com/questions/1887097/why-arent-variable-length-arrays-part-of-the-c-standard) – 463035818_is_not_an_ai Mar 05 '21 at 14:48
  • Variable Length Arrays (VLAs) are *not* part of C++ (though some compilers support them as an extension). But even those that do (if they follow the C rules for VLAs) would likely not allow you to initialize them. I guess you have multiple causes of undefined behaviour. (Including the error pointed out by @AyxanHaqverdili.) – Adrian Mole Mar 05 '21 at 14:49
  • 1
    There is so much wrong with this single line of code `int Arr[Len] = { 'EsNecesarioInicializarElArray' };`. Why are you not using `std::string` for a string ? – 463035818_is_not_an_ai Mar 05 '21 at 14:49
  • Combine your three loops, and get rid of `Arr` – ChrisMM Mar 05 '21 at 14:50
  • @largest_prime_is_463035818 Hmm, probably because I don't know how to do it and because when I initialized the array the code did the work? – Revolucion for Monica Mar 05 '21 at 14:52
  • frankly, you also don't know how to use c-arrays correctly (no shame at all, I am not fluent with them either), `std::string` is simpler, not more difficult to use – 463035818_is_not_an_ai Mar 05 '21 at 14:54
  • @RevolucionforMonica -- You should be using `if (isalpha(Nombre[i]))`, and not `if(Nombre[i] >= 'A' && Nombre[i] <= 'Z'){`. There are multiple reasons why `isalpha` should be used. 1) The system knows what is an alphabetic character. 2) Unless it is ASCII, there is no guarantee that the alphabetic characters are contiguous in the collating sequence. 3) Portability (related to 1). – PaulMcKenzie Mar 05 '21 at 15:41

3 Answers3

1

You should just get rid of the Arr variable entirely, and conio for that matter. It's using non-standard code. Your three loops can be combined into one using if-else-if statements, which allows your to get rid of the Arr variable easily.

void ConvMl_(char Nombre[], int Len){
    
    for(int i=0;i<Len;i++){
        if(Nombre[i] == ' '){
            Nombre[i] = '_';
        } else if(Nombre[i] >= 'A' && Nombre[i] <= 'Z'){
            Nombre[i] = tolower(Nombre[i]);
        } else if(Nombre[i] >= 'a' && Nombre[i] <= 'z' ){
            Nombre[i] = toupper(Nombre[i]);
        }
    }
}
ChrisMM
  • 8,448
  • 13
  • 29
  • 48
1

There is so much wrong with your code. You don't need a separate array and 3 loops. Just do all the conversions you want in a single loop. This answer uses std::transform:

#include <algorithm>
#include <cctype>
#include <cstdio>

int main() {
  char str[] = "Hello World";

  std::transform(std::begin(str), std::end(str), std::begin(str), 
    [](unsigned char const ch) -> char {
      if (std::isspace(ch)) return '_';
      if (std::isupper(ch)) return std::tolower(ch);
      if (std::islower(ch)) return std::toupper(ch);
      return ch;
    });

  std::puts(str);
}

Live

Aykhan Hagverdili
  • 28,141
  • 6
  • 41
  • 93
0

To answer the question rather than to review the code (the code review site is really the place for that, do check it out), if you don't initialise the array, then the values in it are undefined. In practice, they will be whatever was in the memory at the array's address before the code ran. It just so happens that something is leaving a 1 in the memory at the location equivalent to Arr + 4 so Arr[i] != 1 fails for i equal to 4 and the letter i does not get converted.

If you wrote a zero every time you didn't write a 1 then it should work, though as the other answers suggest the code could be a lot more idiomatic and portable C++ and the Arr array is not really required.

Pete Kirkham
  • 48,893
  • 5
  • 92
  • 171