I am passing arguments to main with this code:
#include <stdio.h>
int main(int argc, char ** argv)
{
int i = 1;
for(i = 1; i < argc; i++)
printf("%c", argv[i]);
return 0;
}
So I use ./test 218 abc 392990xFF[w2 dlx which works fine. However, the array is:
arr[1] = "218"
arr[2] = "abc"
arr[3] = "392990xFF[w2"
arr[4] = "dlx"
I want the array to be like this:
arr[0] = '2'
arr[1] = '1'
arr[2] = '8'
arr[3] = 'a'
etc...
How can I achieve this without putting a space after each digit or character?
The arguments passed by the run time environment to the program can be captured by main using int argc, char** argv only. If you have a need to combine them into one large array, you'll need to write the code for that, or print them one character at a time.
int main(int argc, char ** argv)
{
int i = 1;
int j;
int len;
for(i = 1; i < argc; i++)
{
len = strlen(argv[i]);
for ( j = 0; j < len; ++j )
{
printf("%c", argv[i][j]);
}
}
return 0;
}
First of all this is not what it will print -
arr[0] = "218"
arr[1] = "abc"
arr[2] = "392990xFF[w2"
arr[3] = "dlx"
argv[0] will store ./test. And "218" will be on index 1 thus others similarly .
And also printf("%c", argv[i]); .%c expects a char and you pass a string which is incorrect.
Solution could be -
#include <stdio.h>
int main(int argc, char ** argv)
{
int i = 1,j;
for(i = 1; i <argc; i++)
for(j=0;argv[i][j]!='\0';j++)
printf("%c\n", argv[i][j]);
return 0;
}
Rather than a for loop, you can also simply use pointers and while loops instead. There are generally many ways to solve problems in C:
#include <stdio.h>
int main (int argc, char **argv) {
int i = 1;
int j = 0;
while (i < argc) {
char *p = argv[i];
while (*p) {
printf (" arr[%2d] = \"%c\"\n", j++, *p);
p++;
}
i++;
}
return 0;
}
Output
$ ./bin/argvchars 218 abc 392990xFF[w2 dlx
arr[ 0] = "2"
arr[ 1] = "1"
arr[ 2] = "8"
arr[ 3] = "a"
arr[ 4] = "b"
arr[ 5] = "c"
arr[ 6] = "3"
arr[ 7] = "9"
arr[ 8] = "2"
arr[ 9] = "9"
arr[10] = "9"
arr[11] = "0"
arr[12] = "x"
arr[13] = "F"
arr[14] = "F"
arr[15] = "["
arr[16] = "w"
arr[17] = "2"
arr[18] = "d"
arr[19] = "l"
arr[20] = "x"
Determine the total number of characters in all of the strings, then allocate a new character array of that length, and then copy the input characters into the new array.
The last part could take advantage of the sizes you gather in the first part: have an outer loop over all the argument strings, with an inner loop over the characters in each string.
EDIT: Now that I'm not on a mobile device, here's the above in code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char ** argv)
{
//For storing sizes of each input string
int *arg_chars;
//Where the individual characters are stored
char *stored_chars;
/* Determine total number of characters, and store
characters in each word for later re-use */
arg_chars = malloc(argc * sizeof(int));
int total_chars = 0;
//Loop starts at 1 since we don't care about arg 0
for(int i=1; i<argc; i+=1)
{
arg_chars[i] = strlen(argv[i]);
total_chars += arg_chars[i];
printf("Word %d is %d long\n", i, arg_chars[i]);
}
/* Load argument characters into the stored_chars array */
stored_chars = malloc(total_chars * sizeof(char));
int current_char = 0;
//Loop starts at 1 to exclude the program name (arg 0)
for(int i = 1; i < argc; i+=1)
{
printf("Scanning word %d (%s):\n", i, argv[i]);
for(int j = 0; j < arg_chars[i]; j+=1)
{
stored_chars[current_char] = argv[i][j];
printf(" Stored letter %d `%c` (letter %d of word %d)\n", current_char, argv[i][j], j, i);
current_char += 1;
}
}
/* Demonstrate that it's all loaded and accessible in any order */
for(int i=total_chars-1; i >= 0; i-=1)
{
printf("stored_chars[%d] = `%c`\n", i, stored_chars[i]);
}
return 0;
}
Output:
Word 1 is 3 long
Word 2 is 3 long
Word 3 is 12 long
Word 4 is 3 long
Scanning word 1 (218):
Stored letter 0 `2` (letter 0 of word 1)
Stored letter 1 `1` (letter 1 of word 1)
Stored letter 2 `8` (letter 2 of word 1)
Scanning word 2 (abc):
Stored letter 3 `a` (letter 0 of word 2)
Stored letter 4 `b` (letter 1 of word 2)
Stored letter 5 `c` (letter 2 of word 2)
Scanning word 3 (392990xFF[w2):
Stored letter 6 `3` (letter 0 of word 3)
Stored letter 7 `9` (letter 1 of word 3)
Stored letter 8 `2` (letter 2 of word 3)
Stored letter 9 `9` (letter 3 of word 3)
Stored letter 10 `9` (letter 4 of word 3)
Stored letter 11 `0` (letter 5 of word 3)
Stored letter 12 `x` (letter 6 of word 3)
Stored letter 13 `F` (letter 7 of word 3)
Stored letter 14 `F` (letter 8 of word 3)
Stored letter 15 `[` (letter 9 of word 3)
Stored letter 16 `w` (letter 10 of word 3)
Stored letter 17 `2` (letter 11 of word 3)
Scanning word 4 (d1x):
Stored letter 18 `d` (letter 0 of word 4)
Stored letter 19 `1` (letter 1 of word 4)
Stored letter 20 `x` (letter 2 of word 4)
stored_chars[20] = `x`
stored_chars[19] = `1`
stored_chars[18] = `d`
stored_chars[17] = `2`
stored_chars[16] = `w`
stored_chars[15] = `[`
stored_chars[14] = `F`
stored_chars[13] = `F`
stored_chars[12] = `x`
stored_chars[11] = `0`
stored_chars[10] = `9`
stored_chars[9] = `9`
stored_chars[8] = `2`
stored_chars[7] = `9`
stored_chars[6] = `3`
stored_chars[5] = `c`
stored_chars[4] = `b`
stored_chars[3] = `a`
stored_chars[2] = `8`
stored_chars[1] = `1`
stored_chars[0] = `2`
Related
Example:
player 1 enters "all"
player 2 enters "do"
Expected Result: Tie!
Actual Result: Player 2 Wins! (do ends up valuing at 4 points
#include <ctype.h>
#include <cs50.h>
#include <stdio.h>
#include <string.h>
// Points assigned to each letter of the alphabet
int POINTS[] = {1, 3, 3, 2, 1, 4, 2, 4, 1, 8, 5, 1, 3, 1, 1, 3, 10, 1, 1, 1, 1, 4, 4, 8, 4, 10};
int compute_score(string word);
int main(void)
{
// Get input words from both players
string word1 = get_string("Player 1: ");
string word2 = get_string("Player 2: ");
// Score both words
int score1 = compute_score(word1);
int score2 = compute_score(word2);
// TODO: Print the winner
if (score1 > score2)
{
printf("Player 1 wins!");
}
else if (score1 == score2)
{
printf("It's a tie!");
}
else
{
printf("Player 2 wins!");
}
}
int compute_score(string word)
{
// TODO: Compute and return score for string
// set initial score to 0
int score = 0;
int letter = 0;
char lower_word[strlen(word)];
// lowercasing the letters in word
for (int j = 0; j < strlen(word); j++)
{
lower_word[j]= tolower(word[j]);
}
// cycle through the string
for (int i = 0, n = strlen(lower_word); i < n; i++)
{
// check to see if character is within scorable range
if (lower_word[i] >= 'a' && lower_word[i] <= 'z')
{
// make the value be within the list of points
letter = lower_word[i] - 97;
// grab score and add it to current score
score = score + POINTS[letter];
}
// if score isn't a value within the range
else
{
// add nothing to the current score
score = score + 0;
}
}
// returns final score value
return score;
}
It seems the following piece in compute_score leads to error:
char lower_word[strlen(word)];
Assuming strlen(word) is 5, then lower_word has 5 char space (5 bytes). BUT, in C, a char string needs 1 more byte to contain the ending '\0'; so actually lower_word needs 6 bytes to contain a char string.
In your code, lower_word has no (guarantted) ending '\0', so the strlen(lower_word) in the follong loop may work for unknown times...
for (int i = 0, n = strlen(lower_word); i < n; i++)
What modification I suggest is:
char lower_word[strlen(word) + 1] = {0};
What I want the program to do is to evaluate the 2 consecutive integers after another in a set of array, then convert these integers to a corresponding character.
For example, if I have array[10] = {4 2 3 2 5 3 5 3 6 3}, the first 2 ints 4 2 will be converted into "H", 3 2 = E, 5 3 = L and so on until it prints the word HELLO. The program should accept a list of integers.
This is what I've done so far..
#include <stdio.h>
#include <stdlib.h>
int main() {
int i=0, j=0, k=0;
int array[1000];
char space;
printf("Input integers to convert into a string: ");
do {
scanf("%d%c", &array[i], &space);
i++;
} while(space != '\n');
for(/*what should I include here?*/)
if (array[0] == 2 && array[1] == 1)
printf("A");
else if (array[0] == 2 && array[1] == 2)
printf("B");
/* and so may else ifs*/
}
Something like this should work. Instead of going through the for loop one int at a time, it would probably be best to do two at a time.
for(int i = 0; i < 1000; i += 2){
if (array[i] == 2 && array[i + 1] == 1)
printf("A");
else if (array[i] == 2 && array[i + 1] == 2)
printf("B");
/* and so may else ifs*/
}
I would create a function that converts the integers to the characters.
char int_to_char(int val)
{
if(val == 21)
return 'A';
if(val == 22)
return 'B';
if(val == 42)
return 'H';
if(val == 32)
return 'E';
if(val == 53)
return 'L';
if(val == 63)
return 'O';
// I don't see you pattern, so I don't know which value
// is which character
return '?';
}
I don't see your pattern here.
Then your loop would look like:
// i is the number of entered values
// making sure that the end condition is even
for(int j = 0; j < i&1 ? i - 1 : i; j += 2)
{
printf("%c", int_to_char(array[j] * 10 + array[j+1]));
}
This would print HELLO with the input 4 2 3 2 5 3 5 3 6 3.
I am a newbie to C and want to print some special elements of an array.
//Partial code here
char aaa[18] ;
int i = 0;
while(i < 18) {
aaa[i] = '#' ;
printf("%c", aaa[i]) ;
i = i + 4 ;
}
It's supposed to prints 4 # of aaa[0] ,aaa[4],aaa[8],aaa[12],aaa[16]. But it is not. It is printing them in a row like #####. But I don't want those .
I'm assuming you want to eventually print a string and get output like this
"# # # # # "
minus the quotes.
You can do this by filling in a null-terminated string and then printfing that, like so:
// +1 for space for a null terminator
// = {0}; fills the array with 0s
char aaa[18+1] = {0};
// for loop is more idiomatic for looping over an array of known size
for (int i = 0; i < 18; i += 4) {
// if the remainder of dividing i by 4 is equal to 0
if (i % 4 == 0) {
// then put a '#' character in the array at aaa[i]
aaa[i] = '#';
} else {
// otherwise put a ' ' character in the array at aaa[i]
aaa[i] = ' ';
}
}
printf("%s", aaa);
As you're adding 4 to the i variable in each cycle you're printing the positions 0, 4, 8, 12, 16 of the array consecutively.
If you want to print the vector with # as the 4*nth element you should do something like:
while( i < 18 )
{
if( i % 4 == 0 )
{
aaa[i] = '#';
printf("%c" ,aaa[i]);
}
else
printf(" "); // Assuming you want a space in between prints
i++;
}
I'm taking an edx course called CS50. Maybe some of you are familiar with it.
One of the problems set asks you to implement an algorithm to crack a password that was hashed using des-based encryption and is up to 4 characters.
So far, so good. I've done it.
But I decided to improve it a little bit and make it possible to crack passwords that are up to 8 characters, which is the maximum for des-based encryption.
And the problem is, when I add the possibility of the fifth character (or more), my code doesn't work anymore.
Here are my codes
This one is working:
#define _XOPEN_SOURCE
#include <stdio.h>
#include <unistd.h>
#include <string.h>
/*
Use this to compile
clang -ggdb3 -O0 -std=c11 -Wall -Werror -Wshadow crack4.c -lcrypt -lm -o crack4
*/
int main(int argc, char *argv[])
{
if (argc != 2) //Checks if number of command-line arguments is valid
{
printf ("usage: ./crack + hash \n");
return 1; //Retuns 1 (error)
}
char *hash = argv[1]; //Gets hash passed as argument
char salt[3]; //Gets the salt
salt[0] = hash[0];
salt[1] = hash[1];
salt[2] = '\0';
//All possible characters used in a DES-based hashed password (taken from gnu library)
const char *const seedchars = " ./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
char text[9] = "\0"; //Text that is gonna be tried with crypt()
for (int d = 0; d <= 64 ; d++) //To check for passwords of up to 4 characters
{
printf("d %d \n", d);
if(d > 0)
{
text[4] = '\0'; //Defining null-terminator at index 4
text[3] = seedchars[d]; //Iterates through the seedchars list at index 3
}
for (int c = 0; c <= 64 ; c++) //To check for passwords of up to 3 characters
{
if(c > 0)
{
if (d == 0)
{
text[3] = '\0'; //Defining null-terminator at index 3
}
text[2] = seedchars[c]; //Iterates through the seedchars list at index 2
}
for (int b = 0; b <= 64 ; b++) //To check for passwords of up to 2 characters
{
if(b > 0)
{
if (c == 0 && d == 0)
{
text[2] = '\0'; //Defining null-terminator at index 2
}
text[1] = seedchars[b]; //Iterates through the seedchars list at index 1
}
for (int a = 0; a <= 64 ; a++) //To check for passwords of up to 1 character
{
if(b == 0 && c == 0 && d == 0)
{
text[1] = '\0'; //Defining null-terminator at index 1
}
text[0] = seedchars[a]; //Iterates through the seedchars list at index 0
char *password = crypt(text, salt); //Hash var text and save it to var password
if (strcmp(hash, password) == 0) //Compares the hash passed as argv with created above
{
printf("%s\n", text); //prints the text that led to said hash
return 0; //Returns 0 (okay)
}
}
}
}
}
return 1; //Retuns 1 (error)
}
This one isn't working:
#define _XOPEN_SOURCE
#include <stdio.h>
#include <unistd.h>
#include <string.h>
/*
Use this to compile
clang -ggdb3 -O0 -std=c11 -Wall -Werror -Wshadow crack.c -lcrypt -lm -o crack
*/
int main(int argc, char *argv[])
{
if (argc != 2) //Checks if number of command-line arguments is valid
{
printf ("usage: ./crack + hash \n");
return 1; //Retuns 1 (error)
}
char *hash = argv[1]; //Gets hash passed as argument
char salt[3]; //Gets the salt
salt[0] = hash[0];
salt[1] = hash[1];
salt[2] = '\0';
//All possible characters used in a DES-based hashed password (taken from gnu library)
const char *const seedchars = "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
char text[9] = "\0"; //Text that is gonna be tried with crypt()
for (int h = 0; h <= 64 ; h++) //To check for passwords of up to 8 characters
{
if(h > 0)
{
text[8] = '\0'; //Defining null-terminator at index 8
text[7] = seedchars[h]; //Iterates through the seedchars list at index 7
}
for (int g = 0; g <= 64 ; g++) //To check for passwords of up to 7 characters
{
if(g > 0)
{
if (h == 0)
{
text[7] = '\0'; //Defining null-terminator at index 7
}
text[6] = seedchars[g]; //Iterates through the seedchars list at index 6
}
for (int f = 0; f <= 64 ; f++) //To check for passwords of up to 6 characters
{
if(f > 0)
{
if (g == 0 && h == 0)
{
text[6] = '\0'; //Defining null-terminator at index 6
}
text[5] = seedchars[f]; //Iterates through the seedchars list at index 5
}
for (int e = 0; e <= 64 ; e++) //To check for passwords of up to 5 characters
{
if(e > 0)
{
if (f == 0 && g == 0 && h == 0)
{
text[5] = '\0'; //Defining null-terminator at index 5
}
text[4] = seedchars[e]; //Iterates through the seedchars list at index 4
for (int d = 0; d <= 64 ; d++) //To check for passwords of up to 4 characters
{
printf("d %d \n", d);
if(d > 0)
{
if (e == 0 && f == 0 && g == 0 && h == 0)
{
text[4] = '\0'; //Defining null-terminator at index 4
}
text[3] = seedchars[d]; //Iterates through the seedchars list at index 3
}
for (int c = 0; c <= 64 ; c++) //To check for passwords of up to 3 characters
{
if(c > 0)
{
if (d == 0 && e == 0 && f == 0 && g == 0 && h == 0)
{
text[3] = '\0'; //Defining null-terminator at index 3
}
text[2] = seedchars[c]; //Iterates through the seedchars list at index 2
}
for (int b = 0; b <= 64 ; b++) //To check for passwords of up to 2 characters
{
if(b > 0)
{
if (c == 0 && d == 0 && e == 0 && f == 0 && g == 0 && h == 0)
{
text[2] = '\0'; //Defining null-terminator at index 2
}
text[1] = seedchars[b]; //Iterates through the seedchars list at index 1
}
for (int a = 0; a <= 64 ; a++) //To check for passwords of up to 1 character
{
if(b == 0 && c == 0 && d == 0 && e == 0 && f == 0 && g == 0 && h == 0)
{
text[1] = '\0'; //Defining null-terminator at index 1
}
text[0] = seedchars[a]; //Iterates through the seedchars list at index 0
char *password = crypt(text, salt); //Hash var text and save it to var password
if (strcmp(hash, password) == 0) //Compares the hash passed as argv with created above
{
printf("%s\n", text); //prints the text that led to said hash
return 0; //Returns 0 (okay)
}
}
}
}
}
}
}
}
}
}
return 1; //Retuns 1 (error)
}
I'm using the hash below in both codes but it doesn't work on the second code.
hash - 50fkUxYHbnXGw
text - rofl
Can someone please help me understand why is it not working?
Thanks.
Edit:
The second code just finished running and it actually is working but it's taking way longer to crack the password. Here's a screenshot:
I'm not being able to post it as a image for some reason, so here's the link http://imgur.com/a/GVWar
Edit 2: adding link to image and fixing title
Edit 3: re-fixing title
In the first case, for 4 characters, you have 4 nested loops. Which "for" will execute up to 64 times. So your code may run 64 ^ 4 = 16 million times.
In the second case, for 8 characters, you have 8 nested loops. That makes 64 ^ 8 = 281 trillion times.
The time your computer takes to execute the algoritm is proportional to that amount of loops.
It grows so fast because your algorithm is exponential on the number of characters. If you want to learn more, search for "algorithm asymptotic notation".
You can think of a - h as wheels of comprised of 65 characters, with indexes 0 through 64. The last character is a line terminator from the declared value.
If you were to add a printf for the value of e:
crack08 50fkUxYHbnXGw
e 1
d 0
d 1
d 2
d 3
d 4
d 5
d 6
d 7
d 8
d 9
d 10
d 11
d 12
d 13
d 14
d 15
d 16
d 17
d 18
d 19
d 20
d 21
d 22
d 23
...
d 63
d 64
e 2
d 0
d 1
d 2
...
You'd see we'd skip over the first value of e because h - f are 0.
Finding a 4 character match is then deferred until e = 64 (the 65th index the '\0' string terminator).
That represents more than 65 times longer before finding a 4 character password.
Getting rid of the extra passes involves reorganizing the 'wheel' of characters used, adding a '\0' character as the first character, using that as string terminator for the first pass and skipping over it for subsequent passes:
#define _XOPEN_SOURCE
#include <stdio.h>
#include <unistd.h>
#include <string.h>
int main(int argc, char *argv[])
{
if (argc != 2) {
printf ("usage: ./crack hash\n");
return 1; //Retuns 1 (error)
}
char *hash = argv[1];
char salt[3];
salt[0] = hash[0];
salt[1] = hash[1];
salt[2] = '\0';
# define WHEEL_SIZE 65 // all possible password characters
// plus null character for shorter strings
char seedchars[WHEEL_SIZE] =
"#./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
char text[9]; // Text that is gonna be tried with crypt()
text[8] = '\0'; // for h > 0
seedchars[0] = '\0'; // test for short strings first
int a_first = 0;
int b_first = 0;
int c_first = 0;
int d_first = 0;
int e_first = 0;
int f_first = 0;
int g_first = 0;
for (int h = 0; h <= WHEEL_SIZE - 1 ; h++) {
text[7] = seedchars[h];
for (int g = g_first ; g <= WHEEL_SIZE - 1; g++) {
text[6] = seedchars[g];
for (int f = f_first; f <= WHEEL_SIZE -1; f++) {
text[5] = seedchars[f];
for (int e = e_first; e <= WHEEL_SIZE - 1; e++) {
printf("e %2d\n", e);
text[4] = seedchars[e];
for (int d = d_first; d <= WHEEL_SIZE - 1; d++) {
printf("d %2d\n", d);
text[3] = seedchars[d];
for (int c = c_first; c <= WHEEL_SIZE - 1; c++) {
if (c > 0)
b_first = 1;
text[2] = seedchars[c];
for (int b = b_first; b <= WHEEL_SIZE - 1; b++) {
text[1] = seedchars[b];
for (int a = a_first; a <= WHEEL_SIZE - 1; a++) {
text[0] = seedchars[a];
char *password = crypt(text, salt);
if (strcmp(hash, password) == 0) {
printf("%s\n", text);
return 0;
}
}
b_first = 1;
}
c_first = 1;
}
c_first = 1;
}
d_first = 1;
}
e_first = 1;
}
f_first = 1;
}
g_first = 1;
}
return 1;
}
And that gives us the answer in the minimum time:
crack 50fkUxYHbnXGw
e 0
d 0
d 1
d 2
d 3
d 4
d 5
d 6
d 7
d 8
d 9
d 10
d 11
d 12
d 13
d 14
d 15
d 16
d 17
d 18
d 19
d 20
d 21
d 22
d 23
d 24
d 25
d 26
d 27
d 28
d 29
d 30
d 31
d 32
d 33
d 34
d 35
d 36
d 37
d 38
d 39
d 40
d 41
d 42
d 43
d 44
d 45
d 46
d 47
d 48
d 49
d 50
rofl
A much more satisfactory answer.
#include <stdio.h>
void main(){
int i, j, n;
int num[5];
int serial;
for(i=0; i<5; ++i){
scanf("%d",&num[i]);
if(num[i]==num[i-1])
serial=i;
else
continue;
}
printf("Serial number of equal numbers next to each other:%d. %d.", serial-1, serial);
}
This may be hard to understand because I'm not a native English speaker.
If the numbers next to each other are equal the program should print the serial number of those numbers.
For example:
Input: 1 2 3 7 7 7 6;
Output: 3. 4. 5.
Input: 5 5 5 5 5
Output: 0. 1. 2. 3. 4.
I made some changes now it prints the serial of two equal numbers.
I: 1 2 2 3 4 - O: 1. 2.
But what if all the numbers are equal?
// ...
// deal with index 0
if (num[0] == num[1]) printf("0. ");
// deal with indexes 1 .. N - 2
for (int k = 1; k < n - 1; k++) {
if ((num[k - 1] == num[k]) || (num[k] == num[k + 1])) {
printf("%d. ", k);
}
}
// deal with index N - 1
if (num[n - 2] == num[n - 1]) printf("%d. ", n - 1);
// ... possibly with a printf("\n"); somewhere
You can solve this without storing the numers in an array, but you must keep track of how many equal numbers have been read before reading the present one:
#include <stdlib.h>
#include <stdio.h>
int main(void)
{
int i = 0; // running index
int prev = 0; // previously read number
int iprev = 0; // start of range of equal numbers previously read
int n; // currently read number
while (scanf("%d", &n) == 1) {
if (n != prev) {
if (i - iprev > 1) {
while (iprev < i) printf("%d\n", iprev++);
}
iprev = i;
prev = n;
}
i++;
}
if (i - iprev > 1) {
while (iprev < i) printf("%d\n", iprev++);
}
return 0;
}
You consider stretches of equal numbers only after you read a number that terminates the current range of equal numbers. When all numbers are different, the size of that range is 1 and we don't print anything. If the range is larger than 1, print all indices in question.
Because you don't notice a change after reading the last number, you must check the last range separately after the main loop.
If you can put a non-numeric character in the [0] element of your array, you won't need a different test for the first element
int main (void)
{
/* non-numeric in position 0 of data array */
char myList[] = {'.','1','2','2','3','4','4','4','5','6','6'};
int listSz = strlen(myList) -1;
int n;
/* check everything except last */
for (n = 1; n < listSz; n++) {
if(( myList[n] == myList[n +1]) || ( myList[n] == myList[n -1] )) {
printf("%d . ", n);
}
}
/* check last */
if( myList[listSz] == myList[listSz -1] ) {
printf("%d", n);
}
printf("\n");
}
Output: 2 . 3 . 5 . 6 . 7 . 9 . 10