-1

First of all, im new to coding and I thought sometime about the problem and I tried to google it. I already have a workaround I just want to know if it is possible in another way. Im taking the cs50 course and I should write an encryption function.

My problem is, that my char gets temporarily bigger then 127 and then gets truncated. So is it nevertheless possible to calculate with a certain char temporarily before I save it it into a memory address and truncate it?

The part where I think the problem should be:

for
(int i = 0; i < strlen(ui); i++)
{
    if
    (isupper(ui[i]))
        {
            ui[i] += key;
            if
            (ui[i] > 90)
            {
                ui[i] -= 26;
            }
        }
    if
    (islower(ui[i]))
        {   
            ui[i] += key;
            if
            (ui[i] > 122)
            {
                ui[i] -= 26;
            }
        }

and it gets truncated e.g. if the key gets bigger then 6 for an input of z.

So can I write it somehow, that the 26 gets subtracted before it gets into storage or is (what I think atm) not possible because as soon as it gets bigger then 127 even if it is in one line, it gets truncated?

Workaround ( I thought about writing now): I will subtract 96 before so I get calculate with numbers between 1 and 27 and add it after.

thank you for advice in advance.

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
TR3478
  • 25
  • 6
  • I would also appreciate other workarounds ofc. – TR3478 Jan 19 '21 at 05:38
  • Your workaround - substract 96 first is one possible way. The other way is to store the data into two data items (say two arrays) and then add them together when you further process (e.g. all data items are in two array say ui and vi . If the value is say 100 then ui[0]=100 and vi[0]=0, if the value is say 200 then ui[0]=127 and vi[0]=73. There are of course other alternatives , just think out of the box – Ken Lee Jan 19 '21 at 05:49
  • 1
    Firstly, by "truncated" it sounds like you actually mean it overflows. For signed values, the behavior of overflow is undefined (or at least implementation-defined). Normally, such math should be performed with `unsigned char` if you expect this. Furthermore, your hard-coded ASCII value constants are not advisable. Consider something like `'A' + (u[i] - 'A' + key) % 26`. If performance is important, you might consider using a lookup table for each value, eliminating the need for any calls to `isupper`, or any branching. – paddy Jan 19 '21 at 05:49
  • Thanks for your explanations. I already learnt new things and got new input to dig deeper into! – TR3478 Jan 19 '21 at 05:55
  • 1
    Off-topic: What an _interesting_ style. Who taught it to you? – the busybee Jan 19 '21 at 06:44
  • @thebusybee are you asking me? I started reading "Programming Principles and Practice Using c++" from stroustrup for like 100 pages but then I switched to the cs50 course from Harvard. And I use google and stack alot ofc. Why is it interesting? – TR3478 Jan 19 '21 at 07:28
  • 1
    Well, I never saw keywords like `if` and `for` on their own lines in some 40 years of programming in C. And I saw a lot of code... – the busybee Jan 19 '21 at 07:30
  • Oh there is a command line tool called "style50" which is written by one of there employees. this recommends it. do you think this is bad style because it produces more lines of code? https://cs50.readthedocs.io/style50/# – TR3478 Jan 19 '21 at 07:40
  • **style50** is a wrapper around artistic style 3.0 C beautifier, the configuration used here is extremely unusual (and IMHO very confusing), what flags do you use? Is this really the default and recommended style? – chqrlie Jan 21 '21 at 23:22
  • 1
    Don't like this style50. If you are new in coding you are on wrong way of thinking. This is C not Lisp. – i486 Jan 21 '21 at 23:27
  • 1
    @chqrlie i checked it again and you are right. maybe I missunderstand the sign "make a space between if and the condition" and "make /n" between if and condition. but written as above the answer is "looks good". I dont like the style above personally so I won't continue it. thanks for pointing it out. – TR3478 Jan 23 '21 at 08:31

2 Answers2

1

My problem is, that my char gets temporarily bigger then 127 and then gets truncated. So is it nevertheless possible to calculate with a certain char temporarily before I save it it into a memory address and truncate it?

Yes, it is possible, and you do not have to do anything special to achieve it. In a C expression, all arithmetic operands of integer types narrower than int are converted to int or wider, and the computation is performed in that wider type, producing a result of that type. It is then narrowed again if necessary for assignment to an object of narrower type.

Note, however, that

  1. A narrowing conversion to a signed integer type has implementation-defined behavior if the initial value cannot be represented in the target type. That can include raising an implementation-defined signal. It is not safe to assume that the most-significant bytes will just be chopped off when they contain values other than zero.

  2. What you describe is not what the code presented actually does. In particular, I take you to be talking about this:

         ui[i] += key;

It is not a problem to compute ui[i] + key in this case, but there is no particular delay there before writing the result to memory. That's what the assignment part of += does.

You would be better off avoiding the situation altogether. For instance,

if (islower((unsigned char) ui[i])) {
    ui[i] = (((ui[i] - 'a') + key) % 26) + 'a';
}

Do also note, however, that that (and your original) assumes that the numeric values of the lower-case letters for a contiguous block. That is frequently true, but not universally so.

John Bollinger
  • 160,171
  • 8
  • 81
  • 157
  • 2
    one remark: it has to be `islower((unsigned char)ui[i])` to be 100% correct – 0___________ Jan 21 '21 at 22:40
  • 1
    Not the point this answer is trying to focus on, @0___________, but yes, the cast is required if the `ui` array can contain elements with negative values, and the OP's code and comments provide no basis for thinking differently. Updated. – John Bollinger Jan 21 '21 at 22:48
0

A possible overflow bug was mentioned in the comments, however, there's probably another bug in the code, maybe, I don't know what your algorithm should be.

Consider when ui[i] is 'Z' (90 ASCII) and the key ':' (58 ASCII). 'Z' is uppercase so the body of the first if statement is executed, resulting in ui[] being 90 + 58 - 26 = 122 which is now 'z', N.B. lowercase.

Now z is lowercase, so the body of the second if also executes which results in ui[] now being 122 + 58 - 26 = 154. This is outside the ASCII range so you get overflow there.

Another example is ui[] = 'A' and key 70. The first if changes ui[] to 65 + 70 - 26 = 109 which is 'm'. This will also trigger the second if statement with overflow resulting again.

I doubt that both if bodies are supposed to be executed on the same value. If not then you need to add an else before the second if.

}
else if (islower(ui[i])) {
    ...
mhawke
  • 84,695
  • 9
  • 117
  • 138
  • The user is prompt to enter a non negative integer as value. And if the input is bigger then 26 i use %26. That should do it or am I missing sth? Thank you for pointing it out, maybe I should have put more code into the question for clarification but I thought Its easier if its less code. – TR3478 Jan 19 '21 at 07:21
  • You're talking about the key being %26? That should be OK. I would still be wary of omitting the `else` in case you later change those values such that an uppercase letter is translated to a lowercase letter. There might be other cases that you don't show or will add later. I don't think that you would want to perform multiple translations on the same byte. – mhawke Jan 19 '21 at 11:27