What to replace in this C Puzzle? - c

Now this is a silly puzzle I got from some exam paper,sadly I am unable to figure it out from last 15 minutes.
#include <stdio.h>
int main(void){
/* <something> */
putchar(*(wer[1]+1));
return 0;
}
What should we replace in place of something in order to get the output e.Now we know putchar takes a int as argument but this code assumes to give a pointer.Does this question is even valid ?

const char *wer[2] = { "failed", "test" };

Since a[i] is the same as *(a + i) by definition, you can transform the putchar() argument into wer[1][1]. So, something like char *wer[2] would be a satisfactory definition, and any values such that wer[1][1] == 'e' will work.

char * wer[] = { "foobar", "he"};

First, in the code you have mentioned the argument to putchar() is
*(wer[1]+1)
which is not a pointer. It seems that wer[1] is some pointer and that address pointed by wer[1] + 1 is dereferenced. So if wer is an array of pointers to int, then putchar argument should be int which is fine.
Now the code in place of something can be
You have not mentioned clearly what does e mean, is e a char or e is 2.71... (Natural logarithm base) In either case it should be easy to get that output with this code.
-AD

An easy answer is:
char **wer;
putchar('e');
return 0;
For example, the complete code would like like:
#include <stdio.h>
int main(int argc, char **argv)
{
/* Something starts here */
char **wer;
putchar('e');
return 0;
/* Something ends here */
putchar(*(wer[1] + 1));
return 0;
}
The output is:
susam#swift:~$ gcc really-silly-puzzle.c && ./a.out && echo
e
susam#swift:~$
A more interesting question would have been: What is the shortest code that can replace /* */ to get the output 'e'?

From the very pedantic point of view, there's no correct answer to the question. The question is invalid. C language itself makes no guarantees about the output of a program if the output does not end in a newline character. See 7.19.2/2
A text stream is an ordered sequence
of characters composed into lines,
each line consisting of zero or more
characters plus a terminating new-line
character. Whether the last line
requires a terminating new-line
character is implementation-defined.
This program output to the standard output, which is a text stream. The output of this program is implementation-dependent, regardless of what you put in place of /* <something> */, meaning that the question might make sense for some specific platform, but it makes no sense as an abstract C language question.
I highly doubt though that your examiners are expecting this kind of pedantry from you :)))

Related

Is there a way to print Runes as individual characters?

Program's Purpose: Rune Cipher
Note - I am linking to my Own GitHub page below
(it is only for purpose-purpose (no joke intended; it is only for the purpose of showing the purpose of it - what I needed help with (and got help, thanks once again to all of you!)
Final Edit:
I have now (thanks to the Extremely Useful answers provided by the Extremely Amazing People) Completed the project I've been working on; and - for future readers I am also providing the full code.
Again, This wouldn't have been possible without all the help I got from the guys below, thanks to them - once again!
Original code on GitHub
Code
(Shortened down a bit)
#include <stdio.h>
#include <locale.h>
#include <wchar.h>
#define UNICODE_BLOCK_START 0x16A0
#define UUICODE_BLOCK_END 0x16F1
int main(){
setlocale(LC_ALL, "");
wchar_t SUBALPHA[]=L"ᛠᚣᚫᛞᛟᛝᛚᛗᛖᛒᛏᛋᛉᛈᛇᛂᛁᚾᚻᚹᚷᚳᚱᚩᚦᚢ";
wchar_t DATA[]=L"hello";
int lenofData=0;
int i=0;
while(DATA[i]!='\0'){
lenofData++; i++;
}
for(int i=0; i<lenofData; i++) {
printf("DATA[%d]=%lc",i,DATA[i]);
DATA[i]=SUBALPHA[i];
printf(" is now Replaced by %lc\n",DATA[i]);
} printf("%ls",DATA);
return 0;
}
Output:
DATA[0]=h is now Replaced by ᛠ
...
DATA[4]=o is now Replaced by ᛟ
ᛠᚣᚫᛞᛟ
Question continues below
(Note that it's solved, see Accepted answer!)
In Python3 it is easy to print runes:
for i in range(5794,5855):
print(chr(i))
outputs
ᚢ
ᚣ
(..)
ᛝ
ᛞ
How to do that in C ?
using variables (char, char arrays[], int, ...)
Is there a way to e.g print ᛘᛙᛚᛛᛜᛝᛞ as individual characters?
When I try it, it just prints out both warnings about multi-character character constant 'ᛟ'.
I have tried having them as an array of char, a "string" (e.g char s1 = "ᛟᛒᛓ";)
And then print out the first (ᛟ) char of s1: printf("%c", s1[0]); Now, this might seem very wrong to others.
One Example of how I thought of going with this:
Print a rune as "a individual character":
To print e.g 'A'
printf("%c", 65); // 'A'
How do I do that, (if possible) but with a Rune ?
I have as well as tried printing it's digit value to char, which results in question marks, and - other, "undefined" results.
As I do not really remember exactly all the things I've tried so far, I will try my best to formulate this post.
If someone spots a a very easy (maybe, to him/her - even plain-obvious) solution(or trick/workaround) -
I would be super happy if you could point it out! Thanks!
This has bugged me for quite some time.
It works in python though - and it works (as far as I know) in c if you just "print" it (not trough any variable) but, e.g: printf("ᛟ"); this works, but as I said I want to do the same thing but, trough variables. (like, char runes[]="ᛋᛟ";) and then: printf("%c", runes[0]); // to get 'ᛋ' as the output
(Or similar, it does not need to be %c, as well as it does not need to be a char array/char variable) I am just trying to understand how to - do the above, (hopefully not too unreadable)
I am on Linux, and using GCC.
External Links
Python3 Cyphers - At GitHub
Runes - At Unix&Linux SE
Junicode - At Sourceforge.io
To hold a character outside of the 8-bit range, you need a wchar_t (which isn't necessarily Unicode). Although wchar_t is a fundamental C type, you need to #include <wchar.h> to use it, and to use the wide character versions of string and I/O functions (such as putwc shown below).
You also need to ensure that you have activated a locale which supports wide characters, which should be the same locale as is being used by your terminal emulator (if you are writing to a terminal). Normally, that will be the default locale, selected with the string "".
Here's a simple equivalent to your Python code:
#include <locale.h>
#include <stdio.h>
#include <wchar.h>
int main(void) {
setlocale(LC_ALL, "");
/* As indicated in a comment, I should have checked the
* return value from `putwc`; if it returns EOF and errno
* is set to EILSEQ, then the current locale can't handle
* runic characters.
*/
for (wchar_t wc = 5794; wc < 5855; ++wc)
putwc(wc, stdout);
putwc(L'\n', stdout);
return 0;
}
(Live on ideone.)
Stored on the stack as a string of (wide) characters
If you want to add your runes (wchar_t) to a string then you can proceed the following way:
using wcsncpy: (overkill for char, thanks chqrlie for noticing)
#define UNICODE_BLOCK_START 0x16A0 // see wikipedia link for the start
#define UUICODE_BLOCK_END 0x16F0 // true ending of Runic wide chars
int main(void) {
setlocale(LC_ALL, "");
wchar_t buffer[UUICODE_BLOCK_END - UNICODE_BLOCK_START + sizeof(wchar_t) * 2];
int i = 0;
for (wchar_t wc = UNICODE_BLOCK_START; wc <= UUICODE_BLOCK_END; wc++)
buffer[i++] = wc;
buffer[i] = L'\0';
printf("%ls\n", buffer);
return 0;
}
About Wide Chars (and Unicode)
To understand a bit better what is a wide char, you have to think of it as a set of bits set that exceed the original range used for character which was 2^8 = 256 or, with left shifting, 1 << 8).
It is enough when you just need to print what is on your keyboard, but when you need to print Asian characters or other unicode characters, it was not enough anymore and that is the reason why the Unicode standard was created. You can find more about the very different and exotic characters that exist, along with their range (named unicode blocks), on wikipedia, in your case runic.
Range U+16A0..U+16FF - Runic (86 characters), Common (3 characters)
NB: Your Runic wide chars end at 0x16F1 which is slightly before 0x16FF (0x16F1 to 0x16FF are not defined)
You can use the following function to print your wide char as bits:
void print_binary(unsigned int number)
{
char buffer[36]; // 32 bits, 3 spaces and one \0
unsigned int mask = 0b1000000000000000000000000000;
int i = 0;
while (i++ < 32) {
buffer[i] = '0' + !!(number & (mask >> i));
if (i && !(i % 8))
buffer[i] = ' ';
}
buffer[32] = '\0';
printf("%s\n", buffer);
}
That you call in your loop with:
print_binary((unsigned int)wc);
It will give you a better understand on how your wide char is represented at the machine level:
ᛞ
0000000 0000001 1101101 1100000
NB: You will need to pay attention to detail: Do not forget the final L'\0' and you need to use %ls to get the output with printf.

Program keeps returning Segmentation Fault [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 5 years ago.
Improve this question
I'm a new person who loves to play around with coding. Recently I was going through a course on edx, and one of the exercises I need to complete has this small code snippet that keeps on giving Segmentation fault. I have taken out the faulty bit (everything else compiles nicely)
#include <stdio.h>
#include <string.h>
#include <cs50.h>
#include <ctype.h>
#include <stdlib.h>
int main (int argc, string argv[])
{
if (argc == 2 && isalpha(argv[1]))
{
int a = 0;
while (argv[1][a] == '\0')
{
a++;
printf("%c\n", argv[1][a]);
}
}
else
{
printf("Usage: ./programname 1-alphabetical word\n");
return 1;
}
}
The problem seems to be here: argv[1][a] but I can't for the life of me find out what, and how to fix it.
(1) isalpha(argv[1]) is wrong. This function expects a single character, but you are passing a pointer-to-string. That will certainly not give you any kind of expected result, and it's probably Undefined Behaviour into the bargain. You either need to loop and check each character, use a more high-level library function to check the entire string, or - as a quick and probably sense-changing fix - just check the 1st character as BLUEPIXY suggested: isalpha( argv[1][0] ) or isalpha( *argv[0] ).
(2) Your while condition is wrong. You are telling it to loop while the current character is NUL. This will do nothing for non-empty strings and hit the next problem #3 for an empty one. You presumably meant while (argv[1][a] != '\0'), i.e. to loop only until a NUL byte is reached.
(3) You increment index a before trying to printf() it. This will index out of range right now, if the input string is empty, as the body executes and then you immediately index beyond the terminating NUL. Even if the loop condition was fixed, you would miss the 1st character and then print the terminating NUL, neither of which make sense. You should only increment a once you have verified it is in-range and done what you need to do with it. So, printf() it, then increment it.
2 and 3 seem most easily soluble by using a for loop instead of manually splitting up the initialisation, testing, and incrementing of the loop variable. You should also use the correct type for indexing: in case you wanted to print a string with millions or billions of characters, an int is not wide enough, and it's just not good style. So:
#include <stddef.h> /* size_t */
for (size_t a = 0; argv[1][a] != '\0'; ++a) {
printf("%c\n", argv[1][a]);
}
isalpha(argv[1]) looks incorrect and should probably be isalpha(argv[1][0])
isalpha takes a character but you entered in a string to the function
another thing that sticks out as wrong is argv[1][a] == '\0' the ==
should be != this will mean that the while loop will stop once it hits the \0
perhaps
if (argc == 2)
{
int a = 0;
while (argv[1][a] != '\0')
{
if (isalpha(argv[1][a])
printf("%c\n", argv[1][a]);
a++;
}
}
may be what you are looking for?
The only reason for the segmentation fault I see is this subexpression of the if statement
if (argc == 2 && isalpha(argv[1]))
^^^^^^^^^^^^^^^^
There is specified an argument of an incorrect type. The expression argv[1] has the type char * while the function requires an object of character type that is interpreted as unsigned char and promoted to the type int.
So when the promoted argument has a negative value (except the EOF value) the function isalpha has undefined behavior.
From the C Standard (7.4 Character handling <ctype.h>)
1 The header <ctype.h> declares several functions useful for
classifying and mapping characters.198) 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.
You should write the if statement either like
if (argc == 2 && isalpha( ( unsigned char )argv[1][0] ) )
or like
if (argc == 2 && isalpha( ( unsigned char )*argv[1] ) )
Also there is a bug in the while statement that will execute never if the argument is not an empty string. I think you mean the following
int a = 0;
while ( argv[1][a] != '\0' )
{
printf("%c\n", argv[1][a]);
a++;
}
or for example like
int a = 0;
while ( argv[1][a] )
{
printf("%c\n", argv[1][a++]);
}

What's wrong with my c code? (it's probably the malloc call) [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 6 years ago.
Improve this question
When I run this code, I get a segmentation fault. I'm sure I'm doing the pointers wrong, but I'm not sure why or how to fix it.
I also included the question I'm trying to answer in picture form.
#include <stdio.h>
#include <stdlib.h>
char * repeat_characters(char *s, int n) {
printf("%s", *s);
char temp;
int length = 0;
int i = 0;
int j = 0;
int k = 0;
char * newString;
while(s[length]) {
length++;
printf("%d", length);
} // finds length of string
newString = (char*) malloc(length*n*sizeof(char));
while(i++ < i*n) {
temp = s[i];
while (j++ < n) {
newString[k] = temp;
printf("%c", temp);
k++;
}
}
printf("%s", newString);
return newString;
}
int main () {
char * string[100];
int numReps = 0;
printf("Enter a string: ");
scanf("%s", string);
printf("\nEnter number of repetitions: ");
scanf("%d", &numReps);
repeat_characters(*string, numReps);
return 0;
}
One of your jobs as a questioner is to shorten your program to the minimum that demonstrates a problem. For instance, the following would give a segmentation fault:
#include <stdio.h>
char * repeat_characters(char *s, int n) {
printf("%s", *s);
return NULL;
}
int main () {
char * string[100];
scanf("%s", string);
repeat_characters(*string, 0);
return 0;
}
Lots of kinds of problems could be pointed out by compiler warnings. So turn those warnings on. If you're using gcc, then try something like gcc -Wall -Wextra -Werror main.c (or look in your compiler's documentation.)
(The -Werror will turn the warnings into errors, and keep you from accidentally ignoring a warning, which I'd say is a good habit for both learners and experts alike.)
printf("%s", *s);
format '%s' expects argument of type 'char*', but argument 2 has type 'int'
Here you have a parameter char *s. Depending on context could either be a pointer to a single character, or a pointer to the first character of a multiple-character sequence.
C strings operate on the convention that it's a multiple character sequence, and that the range of characters is eventually terminated by a '\0' (or 0-valued character). So when you call printf you must be sure that the character pointer you pass in is to such a validly formed sequence.
You are passing in *s, which dereferences the pointer-to-a-character to make it into a single character. If you want to print a single character, then you'd need to use %c, e.g. printf("%c", *s);. But you want to print a C string, so you should drop the dereferencing * and just say printf("%s\n", s). (You will likely want \n to output a newline, because otherwise your prints will all run together.)
(Note: The reason C without warnings didn't complain when you passed a character where a character pointer was expected is due to the "weirdness" of functions like printf and scanf. They don't have a fixed number or type of arguments that they take, so there is less checking...warnings help pick up the slack.)
scanf("%s", string);
format '%s' expects argument of type 'char*', but argument 2 has type 'char**'
Here you have the problem that you've declared s as char * string[100];, which is an array of character pointers, not an array of characters. The duality of a C array being able to behave like a pointer to its first element takes some getting used to, but if you say char string [100]; then string[0] is a char and string can "decay" to a char* synonymous with &string[0]:
Is an array name a pointer?
while(i++ < i*n)
operation on 'i' may be undefined
The compiler is making a technical complaint here, about modifying the variable i in an expression that also uses i. It's warning about whether the i in i*n would see the value before or after the increment. Avoid this kind of expression...and when-and-if the time comes where you care about what you can and can't do like this, read about sequence points.
But put that aside. What did you intend here? Take the nuance of ++ out of it...what about just while (i < i * n)? When would that be false? Why would it be relevant to solving the problem?
Look through your code and perhaps try commenting it more. What are "the invariants", or the things that you can claim about a variable that would be true on each line? If you were asked to defend why the code worked--with no compiler to run it to see--what would be giving you the certainty that it did the right thing?
Then step through it with a debugger and examples, and check your intuition. If you step over a line and don't get what you expect, then that's when it may be time to start thinking of a question to ask which draws the focus to that line.
There's other issues raised in the comments (for instance, that your malloc() doesn't include space for the terminator, and even once you add in 1 for that space you still have to write a '\0' into it...). Generally speaking your program should perform as many free()s as it does malloc()s. Etc. But hopefully this points you in the right direction for the assignment.

C homework - string loops replacements

I know it's a little unorthodox and will probably cost me some downvotes, but since it's due in 1 hour and I have no idea where to begin I thought I'd ask you guys.
Basically I'm presented with a string that contains placeholders in + form, for example:
1+2+5
I have to create a function to print out all the possibilities of placing different combinations of any given series of digits. I.e. for the series:
[9,8,6] // string array
The output will be
16265
16285
16295
18265
18285
18295
19265
19285
19295
So for each input I get (number of digits)^(number of placeholders) lines of output.
Digits are 0-9 and the maximum form of the digits string is [0,1,2,3,4,5,6,7,8,9].
The original string can have many placeholders (as you'd expect the output can get VERY lengthly).
I have to do it in C, preferably with no recursion. Again I really appreciate any help, couldn't be more thankful right now.
If you can offer an idea, a simplified way to look at solving this, even in a different language or recursively, it'd still be ok, I could use a general concept and move on from there.
It prints them in different order, but it does not matter. and it's not recursive.
#include <stdlib.h>
#include <stdio.h>
int // 0 if no more.
get_string(char* s, const char* spare_chr, int spare_cnt, int comb_num){
for (; *s; s++){
if (*s != '+') continue;
*s = spare_chr[comb_num % spare_cnt];
comb_num /= spare_cnt;
};
return !comb_num;
};
int main(){
const char* spare_str = "986";
int num = 0;
while (1){
char str[] = "1+2+5";
if (!get_string(str, spare_str, strlen(spare_str), num++))
break; // done
printf("str num %2d: %s\n", num, str);
};
return 0;
};
In order to do the actual replacement, you can use strchr to find the first occurrence of a character and return a char * pointer to it. You can then simply change that pointer's value and bam, you've done a character replacement.
Because strchr searches for the first occurrence (before a null terminator), you can use it repeatedly for every value you want to replace.
The loop's a little trickier, but let's see what you make of this.

Splitting a string in C into separate parts

I've been trying to write a function in C that detects palindromes. The program currently looks like the following:
#include <stdio.h>
#include <string.h>
int main()
{
char palindrome[24]; int palength; int halflength;
gets(palindrome);
palength = strlen(palindrome);
halflength = palength / 2;
printf("That string is %u characters long.\r\n", palength);
printf("Half of that is %u.\r\n", halflength);
return 0;
}
Right now it detects the length of a string, and also shows what half of that is. This is just to make sure it is working how I think it should be. What the rest of the function should do (if possible) is take the integer from "halflength" and use that to take that amount of characters off of the beginning and end of the string and store those in separate strings. From there I'd be able to compare the characters in those, and be able return true or false if the string is indeed a palindrome.
TL;DR - Is it possible take a certain amount of characters (in this case the integer "halflength") off the front and end of a string and store them in separate variables. Read above for more information on what I'm trying to do.
P.S. - I know not to use gets(), but didn't feel like writing a function to truncate \n off of fgets().
int len = strlen(palindrome) - 1; // assuming no \n
int half = len << 1;
for (int i=0; i<=half; ++i)
if(palindrome[i] != palindrome[len-i])
return false;
return true;
What if you do something like this,
char *str1="lol",*str2;
str2=strrev(str1);
//if both are same then it actually is a palindrome ; )
Found out I was approaching the problem wrong. How I should be doing this is iterating over the characters using a pointer both backwards and forwards. Although if you'd still like to answer the original question it could still be useful at some point.

Resources