Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>The code:</p> <pre><code> char *s = "hello ppl."; </code></pre> <p>gives you a pointer to what it <em>probably</em> read-only memory. That's because string constants in C are non-modifiable. When you try to write to that memory, you'll most likely get a segmentation violation. The relevant part of the standard (<code>C99 6.4.5/6</code> on <code>String literals</code>) states:</p> <blockquote> <p>It is unspecified whether these arrays are distinct provided their elements have the appropriate values. If the program attempts to modify such an array, the behavior is undefined.</p> </blockquote> <p>So, while the memory doesn't <em>have</em> to be read-only, you're still breaking the rules by trying to modify it.</p> <p>Try this instead:</p> <pre><code>char s[] = "hello ppl."; </code></pre> <p>which is conceptually the same as:</p> <pre><code>char s[11]; // for the whole string plus null terminator strcpy (s, "hello ppl."); </code></pre> <p>In other words, it puts the string you want to change into <em>writable</em> memory. The following code:</p> <pre><code>#include &lt;stdio.h&gt; #include &lt;string.h&gt; int main(void) { int i; char s[] = "hello ppl."; for (i = 0; i &lt; strlen(s); i++) { char c = s[i]; if (c &gt;= 97 &amp;&amp; c &lt;= 122) { c += 2; s[i] = c; } } printf("%s\n",s); return 0; } </code></pre> <p>gives you <code>"jgnnq rrn."</code> as you desired.</p> <p>A few other things I'd like to point out which are not fatal:</p> <ul> <li>It's not usually a good idea to use 'magic' numbers like <code>97</code> and <code>122</code>. It's just as easy, and clearer in intent, to use 'a' and 'z'.</li> <li>If you really want to rotate, you can't blindly add 2 to 'y' and 'z'. You have to treat them specially (subtract 24) so that they map correctly to 'a' and 'b'.</li> <li>The C standard doesn't guarantee that alpha characters are contiguous. If you know you're using ASCII, you're probably okay but I thought I'd just mention that. As an aside, it <em>does</em> guarantee that for the numeric characters.</li> </ul> <p>Having said that, I'd rather use a mapping table as follows:</p> <pre><code>#include &lt;stdio.h&gt; #include &lt;string.h&gt; int main (void) { char *lkupPtr, *strPtr; char str[] = "hello ppl."; const char * const from = "abcdefghijklmnopqrstuvwzyz"; const char * const to = "cdefghijklmnopqrstuvwzyzab"; for (strPtr = str; *strPtr != '\0'; strPtr++) if (lkupPtr = strchr (from, *strPtr)) != NULL) *strPtr = to[(int)(lkupPtr - from)]; printf("%s\n",str); return 0; } </code></pre> <p>This takes care of all the points I raised above and you can, if necessary, add more mappings if you're in an internationalized environment (rather than just plain ASCII or EDCDIC).</p> <p>This should be, in my opinion, fast enough for all but the most demanding of requirements (I clocked it at over 3 million characters per second on my PC). If you have a near-insatiable need for performance over and above that, yet don't want to opt for hand-crafted assembly targeted to your specific CPU, you could <em>try</em> something like the following.</p> <p>It's still fully compliant with the C standard but may deliver better performance by virtue of the fact all heavy calculation work is done once at the start. It creates a table holding all possible character values, initializes it so that every character translates to itself by default, then changes the specific characters you're interested in.</p> <p>That removes any checking for characters from the translation itself.</p> <pre><code>#include &lt;stdio.h&gt; #include &lt;string.h&gt; #include &lt;limits.h&gt; static char table[CHAR_MAX + 1]; static void xlatInit (void) { int i; char * from = "abcdefghijklmnopqrstuvwzyz"; char * to = "cdefghijklmnopqrstuvwzyzab"; for (i = 0; i &lt;= CHAR_MAX; i++) table[i] = i; while (*from != '\0') table[*from++] = *to++; } int main (void) { char *strPtr; char str[] = "hello ppl."; xlatInit(); // Do this once only, amortize the cost. for (strPtr = str; *strPtr != '\0'; strPtr++) *strPtr = table[*strPtr]; printf("%s\n",str); return 0; } </code></pre>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload