Access to a specific element on an array using pointers C - c

I am working to replace '.' by '::' in a phrase.
I am given a phrase with 30 caracteres, without using other array. I would like to access to the last element using a pointer.
However,
First I count the dots in my phrase.
actualSize= 0; i= 0; dotNumb= 0;
while (i<actualSize){
if (tab[i]=='.') dotNumb++
i++
}
Now I should start by the end; whenever I find an element I move it, whenever I find a '.' I make an operation two times, by copying ':' two times.
Now I need to access to this element tab[dotNumb+actualSize]
Can I do it this way, or should I use pointers .
int newSize = dotNumb+actualSize ;
int j=newSize ;
int cursor=actualSize;
while (j>0){
if (tab[i]!='.') {tab[j]=tab[cursor]; }
else{tab[j]=':';tab[--j]=':';}
cursor--; j--;
}

The code you wrote does not work, (you made some typos, for example actualSize is set to 0 so the loop counting the dots will never execute. and the logic of your code would delete the character preceding a dot in the original array). You probably want something like that:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main(void) {
char *tab = malloc(30 + 1);
if (tab == NULL) {
return -1;
}
strcpy(tab, "123456789.123456789.123456789.");
printf("Original string: %s\n", tab);
size_t actualSize = strlen(tab);
int dotNumb = 0;
for (int i = 0; i < actualSize; i++) {
if (tab[i]=='.') {
dotNumb++;
}
}
const size_t newSize = dotNumb + actualSize + 1;
tab = realloc (tab, newSize);
if (tab == NULL) {
/* leak memory previously allocated in tab */
return -1;
}
tab[newSize] = '\0'; /* termination character */
int j = newSize ;
for (size_t cursor = actualSize; cursor > 0; cursor--) {
if (tab[cursor] != '.') {
tab[j--] = tab[cursor];
}
else {
tab[j--] = ':';
tab[j--] = ':';
}
}
printf("Modified string: %s\n", tab);
return 0;
}
You can test the code here:
http://ideone.com/YOxJKo

Related

Codewars problem not passing tests but when I put it into GitHub it does what it's supposed to

The instructions for this code wars problem is as follows:
link to the problem: https://www.codewars.com/kata/563b74ddd19a3ad462000054/train/c
"write me a function stringy that takes a size and returns a string of alternating '1s' and '0s'.
the string should start with a 1.
a string with size 6 should return :'101010'.
with size 4 should return : '1010'.
with size 12 should return : '101010101010'.
The size will always be positive and will only use whole numbers."
My solution to this problem is as follows.
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
char *stringy (size_t size)
{
char *s = malloc(sizeof(char) * size);
for(size_t i = 0; i < size ; i++)
{
if(i % 2 == 0)
{
memcpy(&s[i], "1", 1);
}
else
{
memcpy(&s[i], "0", 1);
}
}
return s;
}
This passes for numbers 12 and smaller but when they use larger numbers as size to test I will get extra 1's and 0's added to the end and will get an error like
for size = 41, expected:
"10101010101010101010101010101010101010101"
but got:
"1010101010101010101010101010101010101010101010101".
I've put this code into GitHub and made a variable that increments by one for every iteration of the for loop and used printf statements to print the variable just mentioned and the string of 0's and 1's and this works on GitHub with even larger numbers than 41 or anything they would test with on code wars. Is there something wrong with my code or with the test on code wars?
YOu need space for terminating NULL
And then you have to set the NULL at the end
char *stringy (size_t size)
{
char *s = malloc(sizeof(char) * (size+1)); <<<<========== +1
for( size_t i = 0; i < size ; i++)
{
if(i % 2 == 0)
{
memcpy(&s[i], "1", 1);
}
else
{
memcpy(&s[i], "0", 1);
}
}
s[size] = '\0'; <<<<=== trailing zero
return s;
}
as other have pointed out, memcpy is a huge overkill here, simpler (and less surprising to readers of the code) is
char *stringy (size_t size)
{
char *s = malloc(sizeof(char) * (size+1)); <<<<========== +1
for( size_t i = 0; i < size ; i++)
{
if(i % 2 == 0)
{
s[i] = '1';
}
else
{
s[i] = '0';
}
}
s[size] = '\0'; <<<<=== trailing zero
return s;
}

Try to split string but got messy substrings

I try to split one string to 3-gram strings. But turns out that the resulting substrings were always messy. The length and char ** input... are needed, since I will use them as args later for python calling the funxtion.
This is the function I wrote.
struct strArrIntArr getSearchArr(char* input, int length) {
struct strArrIntArr nameIndArr;
// flag of same bit
int same;
// flag/index of identical strings
int flag = 0;
// how many identical strings
int num = 0;
// array of split strings
char** nameArr = (char **)malloc(sizeof(char *) * (length - 2));
if ( nameArr == NULL ) exit(0);
// numbers of every split string
int* valueArr = (int* )malloc(sizeof(int) * (length-2));
if ( valueArr == NULL ) exit(0);
// loop length of search string -2 times (3-gram)
for(int i = 0; i<length-2; i++){
if(flag==0){
nameArr[i - num] = (char *)malloc(sizeof(char) * 3);
if ( nameArr[i - num] == NULL ) exit(0);
printf("----i------------%d------\n", i);
printf("----i-num--------%d------\n", i-num);
}
flag = 0;
// compare splitting string with existing split strings,
// if a string exists, it would not be stored
for(int k=0; k<i-num; k++){
same = 0;
for(int j=0; j<3; j++){
if(input[i + j] == nameArr[k][j]){
same ++;
}
}
// identical strings found, if all the three bits are the same
if(same == 3){
flag = k;
num++;
break;
}
}
// if the current split string doesn't exist yet
// put current split string to array
if(flag == 0){
for(int j=0; j<3; j++){
nameArr[i-num][j] = input[i + j];
valueArr[i-num] = 1;
}
}else{
valueArr[flag]++;
}
printf("-----string----%s\n", nameArr[i-num]);
}
// number of N-gram strings
nameIndArr.length = length- 2- num;
// array of N-gram strings
nameIndArr.charArr = nameArr;
nameIndArr.intArr = valueArr;
return nameIndArr;
}
To call the function:
int main(int argc, const char * argv[]) {
int length = 30;
char* input = (char *)malloc(sizeof(char) * length);
input = "googleapis.com.wncln.wncln.org";
// split the search string into N-gram strings
// and count the numbers of every split string
struct strArrIntArr nameIndArr = getSearchArr(input, length);
}
Below is the result. The strings from 17 are messy.
----i------------0------
----i-num--------0------
-----string----goo
----i------------1------
----i-num--------1------
-----string----oog
----i------------2------
----i-num--------2------
-----string----ogl
----i------------3------
----i-num--------3------
-----string----gle
----i------------4------
----i-num--------4------
-----string----lea
----i------------5------
----i-num--------5------
-----string----eap
----i------------6------
----i-num--------6------
-----string----api
----i------------7------
----i-num--------7------
-----string----pis
----i------------8------
----i-num--------8------
-----string----is.
----i------------9------
----i-num--------9------
-----string----s.c
----i------------10------
----i-num--------10------
-----string----.co
----i------------11------
----i-num--------11------
-----string----com
----i------------12------
----i-num--------12------
-----string----om.
----i------------13------
----i-num--------13------
-----string----m.w
----i------------14------
----i-num--------14------
-----string----.wn
----i------------15------
----i-num--------15------
-----string----wnc
---i------------16------
----i-num--------16------
-----string----ncl
----i------------17------
----i-num--------17------
-----string----clnsole
----i------------18------
----i-num--------18------
-----string----ln.=C:
----i------------19------
----i-num--------19------
-----string----n.wgram 馻绚s
----i------------20------
----i-num--------20------
-----string----n.wgram 馻绚s
-----string----n.wgram 馻绚s
-----string----n.wgram 馻绚s
-----string----n.wgram 馻绚s
-----string----n.wgram 馻绚s
-----string----n.oiles(騛窑=
----i------------26------
----i-num--------21------
-----string----.orSModu鯽蓼t
----i------------27------
----i-num--------22------
-----string----org
under win10, codeblocks 17.12, gcc 8.1.0
You are making life complicated for you in several places:
Don't count backwards: Instead of making num the count of duplicates, make it the count of unique trigraphs.
Scope variable definitions in functions as closely as possible. You have several uninitialized variables. You have declared them at the start of the function, but you need them only in local blocks.
Initialize as soon as you allocate. In your code, you use a flag to determine whather to create a new string. The code to allocate he string and to initialize it are in different blocks. Those blocks have the same flag as condition, but the flag is updated in between. This could lead to asynchronities, even to bugs when you try to initialize memory that wasn't allocated.
It's probably better to keep the strings and their counts together in a struct. If anything, this will help you with sorting later. This also offers some simplification: Instead of allocating chunks of 3 bytes, keep a char array of four bytes in the struct, so that all entries can be properly null-terminated. Those don't need to be allocated separately.
Here's an alternative implementation:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
struct tri {
char str[4]; // trigraph: 3 chars and NUL
int count; // count of occurrences
};
struct stat {
struct tri *tri; // list of trigraphs with counts
int size; // number of trigraphs
};
/*
* Find string 'key' in list of trigraphs. Return the index
* or in the array or -1 if it isn't found.
*/
int find_trigraph(const struct tri *tri, int n, const char *key)
{
for (int i = 0; i < n; i++) {
int j = 0;
while (j < 3 && tri[i].str[j] == key[j]) j++;
if (j == 3) return i;
}
return -1;
}
/*
* Create an array of trigraphs from the input string.
*/
struct stat getSearchArr(char* input, int length)
{
int num = 0;
struct tri *tri = malloc(sizeof(*tri) * (length - 2));
for(int i = 0; i < length - 2; i++) {
int index = find_trigraph(tri, num, input + i);
if (index < 0) {
snprintf(tri[num].str, 4, "%.3s", input + i); // see [1]
tri[num].count = 1;
num++;
} else {
tri[index].count++;
}
}
for(int i = 0; i < num; i++) {
printf("#%d %s: %d\n", i, tri[i].str, tri[i].count);
}
struct stat stat = { tri, num };
return stat;
}
/*
* Driver code
*/
int main(void)
{
char *input = "googleapis.com.wncln.wncln.org";
int length = strlen(input);
struct stat stat = getSearchArr(input, length);
// ... do stuff with stat ...
free(stat.tri);
return 0;
}
Footnote 1: I find that snprintf(str, n, "%.*s", len, str + offset) is useful for copying substrings: The result will not overflow the buffer and it will be null-terminated. There really ought to be a stanard function for this, but strcpy may overflow and strncpy may leave the buffer unterminated.
This answer tries to fix the existing code instead of proposing alternative/better solutions.
After fixing the output
printf("-----string----%s\n", nameArr[i-num]);
in the question, there is still another important problem.
You want to store 3 characters in nameArr[i-num] and allocate space for 3 characters. Later you print is as a string in the code shown above. This requires a trailing '\0' after the 3 characters, so you have to allocate memory for 4 characters and either append a '\0' or initialize the allocated memory with 0. Using calloc instead of malloc would automatically initialize the memory to 0.
Here is a modified version of the source code
I also changed the initialization of the string value and its length in main() to avoid the memory leak.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct strArrIntArr {
int length;
char **charArr;
int *intArr;
};
struct strArrIntArr getSearchArr(char* input, int length) {
struct strArrIntArr nameIndArr;
// flag of same bit
int same;
// flag/index of identical strings
int flag = 0;
// how many identical strings
int num = 0;
// array of split strings
char** nameArr = (char **)malloc(sizeof(char *) * (length - 2));
if ( nameArr == NULL ) exit(0);
// numbers of every split string
int* valueArr = (int* )malloc(sizeof(int) * (length-2));
if ( valueArr == NULL ) exit(0);
// loop length of search string -2 times (3-gram)
for(int i = 0; i<length-2; i++){
if(flag==0){
nameArr[i - num] = (char *)malloc(sizeof(char) * 4);
if ( nameArr[i - num] == NULL ) exit(0);
printf("----i------------%d------\n", i);
printf("----i-num--------%d------\n", i-num);
}
flag = 0;
// compare splitting string with existing split strings,
// if a string exists, it would not be stored
for(int k=0; k<i-num; k++){
same = 0;
for(int j=0; j<3; j++){
if(input[i + j] == nameArr[k][j]){
same ++;
}
}
// identical strings found, if all the three bits are the same
if(same == 3){
flag = 1;
num++;
break;
}
}
// if the current split string doesn't exist yet
// put current split string to array
if(flag == 0){
for(int j=0; j<3; j++){
nameArr[i-num][j] = input[i + j];
valueArr[i-num] = 1;
}
nameArr[i-num][3] = '\0';
}else{
valueArr[flag]++;
}
printf("-----string----%s\n", nameArr[i-num]);
}
// number of N-gram strings
nameIndArr.length = length- 2- num;
// array of N-gram strings
nameIndArr.charArr = nameArr;
nameIndArr.intArr = valueArr;
return nameIndArr;
}
int main(int argc, const char * argv[]) {
int length;
char* input = strdup("googleapis.com.wncln.wncln.org");
length = strlen(input);
// split the search string into N-gram strings
// and count the numbers of every split string
struct strArrIntArr nameIndArr = getSearchArr(input, length);
}
This other answer contains more improvements which I personally would prefer over the modified original solution.

While splitting one char array into array of char arrays, first array always displayed as random chars

I am doing a school exercise and it's asking us to split a string(character array) into multiple character arrays. A string input like this
"asdf qwerty zxcv"
should result in an array of characters arrays like this
"asdf","qwerty","zxcv"
While I am testing the code, no matter what strings I entered as the argument of my function, the first string printed out would always be some random characters, while the rest are as expected.
"02�9�","qwerty","zxcv"
Besides, my code worked fine in online compilers, which I saved here. I also tested in OnlineGDB, in which the code worked pretty well too.
This is my code with the main function:
#include <stdio.h>
#include <stdlib.h>
int is_separator(char c)
{
if (c == '\n' || c == '\t' || c == ' ' || c == '\0')
{
return (1);
}
else
{
return (0);
}
}
int ct_len(int index, char *str)
{
int i;
i = index;
while (!(is_separator(str[index])))
{
index++;
}
return (index - i);
}
int ct_wd(char *str)
{
int count;
int i;
i = 0;
count = 0;
while (str[i])
{
if (is_separator(str[i]))
count++;
i++;
}
return (count + 1);
}
char **ft_split_whitespaces(char *str)
{
char **tab;
int i;
int j;
int k;
i = 0;
j = 0;
tab = malloc(ct_wd(str));
while (str[j])
{
k = 1;
while (is_separator(str[j]))
j++;
*(tab + i) = (char *)malloc(sizeof(char) * ((ct_len(j, str) + 1)));
while (!(is_separator(str[j])))
{
tab[i][k - 1] = str[j++];
k++;
}
tab[i++][k - 1] = '\0';
}
tab[i] = 0;
return (&tab[0]);
}
int main(void)
{
char** res;
for (res = ft_split_whitespaces("asdf qwerty zxcv"); *res != 0; res++)
{
printf("'%s',", *res);
}
return (0);
}
One hint is that the output of the first array is changing, which suggests that there might be some problems with my memory allocation. However, I am not sure about it. If you can help me find out where the bug is, I would be really appreciative of your help. Thank you very much for reading.
this
tab = malloc(ct_wd(str));
to this
tab = malloc(ct_wd(str) * sizeof(char *));
also you wight want to consider using valgrind, which should provide a fair indication of where the corruption is. essentially ct_wd(str) function is the main culprit along with malloc statement after that. you might want to take a closer look at how much memory you are allocating and how much actually using. as mentioned valgrind should assist you better.
valgrind --tool=memcheck --leak-check=full --track-origins=yes <executalbe>

Attempting to split and store arrays similar to strtok

For an assignment in class, we have been instructed to write a program which takes a string and a delimiter and then takes "words" and stores them in a new array of strings. i.e., the input ("my name is", " ") would return an array with elements "my" "name" "is".
Roughly, what I've attempted is to:
Use a separate helper called number_of_delimeters() to determine the size of the array of strings
Iterate through the initial array to find the number of elements in a given string which would be placed in the array
Allocate storage within my array for each string
Store the elements within the allocated memory
Include directives:
#include <stdlib.h>
#include <stdio.h>
This is the separate helper:
int number_of_delimiters (char* s, int d)
{
int numdelim = 0;
for (int i = 0; s[i] != '\0'; i++)
{
if (s[i] == d)
{
numdelim++;
}
}
return numdelim;
}
`This is the function itself:
char** split_at (char* s, char d)
{
int numdelim = number_of_delimiters(s, d);
int a = 0;
int b = 0;
char** final = (char**)malloc((numdelim+1) * sizeof(char*));
for (int i = 0; i <= numdelim; i++)
{
int sizeofj = 0;
while (s[a] != d)
{
sizeofj++;
a++;
}
final[i] = (char*)malloc(sizeofj);
a++;
int j = 0;
while (j < sizeofj)
{
final[i][j] = s[b];
j++;
b++;
}
b++;
final[i][j+1] = '\0';
}
return final;
}
To print:
void print_string_array(char* a[], unsigned int alen)
{
printf("{");
for (int i = 0; i < alen; i++)
{
if (i == alen - 1)
{
printf("%s", a[i]);
}
else
{
printf("%s ", a[i]);
}
}
printf("}");
}
int main(int argc, char *argv[])
{
print_string_array(split_at("Hi, my name is none.", ' '), 5);
return 0;
}
This currently returns {Hi, my name is none.}
After doing some research, I realized that the purpose of this function is either similar or identical to strtok. However, looking at the source code for this proved to be little help because it included concepts we have not yet used in class.
I know the question is vague, and the code rough to read, but what can you point to as immediately problematic with this approach to the problem?
The program has several problems.
while (s[a] != d) is wrong, there is no delimiter after the last word in the string.
final[i][j+1] = '\0'; is wrong, j+1 is one position too much.
The returned array is unusable, unless you know beforehand how many elements are there.
Just for explanation:
strtok will modify the array you pass in! After
char test[] = "a b c ";
for(char* t = test; strtok(t, " "); t = NULL);
test content will be:
{ 'a', 0, 'b', 0, 'c', 0, 0 }
You get subsequently these pointers to your test array: test + 0, test + 2, test + 4, NULL.
strtok remembers the pointer you pass to it internally (most likely, you saw a static variable in your source code...) so you can (and must) pass NULL the next time you call it (as long as you want to operate on the same source string).
You, in contrast, apparently want to copy the data. Fine, one can do so. But here we get a problem:
char** final = //...
return final;
void print_string_array(char* a[], unsigned int alen)
You just return the array, but you are losing length information!
How do you want to pass the length to your print function then?
char** tokens = split_at(...);
print_string_array(tokens, sizeof(tokens));
will fail, because sizeof(tokens) will always return the size of a pointer on your local system (most likely 8, possibly 4 on older hardware)!
My personal recommendation: create a null terminated array of c strings:
char** final = (char**)malloc((numdelim + 2) * sizeof(char*));
// ^ (!)
// ...
final[numdelim + 1] = NULL;
Then your print function could look like this:
void print_string_array(char* a[]) // no len parameter any more!
{
printf("{");
if(*a)
{
printf("%s", *a); // printing first element without space
for (++a; *a; ++a) // *a: checking, if current pointer is not NULL
{
printf(" %s", *a); // next elements with spaces
}
}
printf("}");
}
No problems with length any more. Actually, this is exactly the same principle C strings use themselves (the terminating null character, remember?).
Additionally, here is a problem in your own code:
while (j < sizeofj)
{
final[i][j] = s[b];
j++; // j will always point behind your string!
b++;
}
b++;
// thus, you need:
final[i][j] = '\0'; // no +1 !
For completeness (this was discovered by n.m. already, see the other answer): If there is no trailing delimiter in your source string,
while (s[a] != d)
will read beyond your input string (which is undefined behaviour and could result in your program crashing). You need to check for the terminating null character, too:
while(s[a] && s[a] != d)
Finally: how do you want to handle subsequent delimiters? Currently, you will insert empty strings into your array? Print out your strings as follows (with two delimiting symbols - I used * and + like birth and death...):
printf("*%s+", *a);
and you will see. Is this intended?
Edit 2: The variant with pointer arithmetic (only):
char** split_at (char* s, char d)
{
int numdelim = 0;
char* t = s; // need a copy
while(*t)
{
numdelim += *t == d;
++t;
}
char** final = (char**)malloc((numdelim + 2) * sizeof(char*));
char** f = final; // pointer to current position within final
t = s; // re-assign t, using s as start pointer for new strings
while(*t) // see above
{
if(*t == d) // delimiter found!
{
// can subtract pointers --
// as long as they point to the same array!!!
char* n = (char*)malloc(t - s + 1); // +1: terminating null
*f++ = n; // store in position pointer and increment it
while(s != t) // copy the string from start to current t
*n++ = *s++;
*n = 0; // terminate the new string
}
++t; // next character...
}
*f = NULL; // and finally terminate the string array
return final;
}
While I've now been shown a more elegant solution, I've found and rectified the issues in my code:
char** split_at (char* s, char d)
{
int numdelim = 0;
int x;
for (x = 0; s[x] != '\0'; x++)
{
if (s[x] == d)
{
numdelim++;
}
}
int a = 0;
int b = 0;
char** final = (char**)malloc((numdelim+1) * sizeof(char*));
for (int i = 0; i <= numdelim; i++)
{
int sizeofj = 0;
while ((s[a] != d) && (a < x))
{
sizeofj++;
a++;
}
final[i] = (char*)malloc(sizeofj);
a++;
int j = 0;
while (j < sizeofj)
{
final[i][j] = s[b];
j++;
b++;
}
final[i][j] = '\0';
b++;
}
return final;
}
I consolidated what I previously had as a helper function, and modified some points where I incorrectly incremented .

User-defined function similar to squeeze()

So I'm trying to do the practice exercises in K&R. It wants me to make a function similar to squeeze, I don't get whats wrong with it. I desk checked it already. I don't want a solution found on the net, I wanna understand why my code wont work.
//removes characters that are present in both strings
#include <stdio.h>
#include <conio.h>
#include <stdlib.h>
#define MAXLTR 15
void removesame(char s1[],char s2[]);
int main(void)
{
char string1[MAXLTR],string2[MAXLTR];
printf("Enter a string: ");
scanf("\n%s",&string1);
printf("\nEnter the letters/words to be removed: ");
scanf("\n%s",&string2);
removesame(string1,string2);
printf("\nFinal output: %s",string1);
getch();
}
void removesame(char s1[],char s2[])
{
char temp[MAXLTR];
int arraycntr,comparecntr;
for(comparecntr = 0; comparecntr < MAXLTR; comparecntr++)
{
for(arraycntr = 0;arraycntr < MAXLTR;arraycntr++)
{
if(s1[arraycntr] == s2[arraycntr])
s1[arraycntr] == '\t';
}
}
comparecntr = 0;
for(arraycntr = 0; arraycntr < MAXLTR; arraycntr++)
{
if(s1[arraycntr] != '\t')
{
temp[comparecntr] = s1[arraycntr];
++comparecntr;
}
}
for(arraycntr = 0; arraycntr < MAXLTR; arraycntr++)
s1[arraycntr] = '\0';
for(arraycntr = 0;arraycntr < MAXLTR; arraycntr++)
s1[arraycntr] = temp[arraycntr];
}
This is not an assignment, but is an equality test:
s1[arraycntr] == '\t';
you meant:
s1[arraycntr] = '\t';
If you compile with a high warning level, the compiler may emit a message alerting you to this. The Microsoft VC compiler emits the following warning:
C:\devel\cpp\stackoverflow\main.c(32) : warning C4553: '==' : operator has no effect; did you intend '='?
The initial for loops only check if s1 and s2 have the same values in the same indexes, it does not check if a char in s1 exists anywhere in s2. The terminating conditions on the for loops should also be the lengths of s1 and s2, not MAXLTR:
size_t arraycntr,comparecntr;
for(comparecntr = 0; comparecntr < strlen(s2); comparecntr++)
{
for(arraycntr = 0;arraycntr < strlen(s1) ;arraycntr++)
{
if(s1[arraycntr] == s2[comparecntr])
s1[arraycntr] = `\t`;
}
}
The next for loop should use strlen(s1) also and just assign null terminator to temp after:
comparecntr = 0;
for(arraycntr = 0; arraycntr < strlen(s1); arraycntr++)
{
if(s1[arraycntr] != `\t`)
{
temp[comparecntr] = s1[arraycntr];
++comparecntr;
}
}
temp[comparecntr] = '\0';
temp is not initialised anywhere, so contains random data, apart from that just entered during this for. Without a null terminator in temp, s1 will end with no null terminator also (you will probably see garbage printed afterwards). Finally, just strlen(temp) + 1 when populating s1:
for(arraycntr = 0;arraycntr < strlen(temp) + 1; arraycntr++)
s1[arraycntr] = temp[arraycntr];
The + 1 will copy the null terminator to s1.
Minor note, instead of calling strlen() in the terminating condition of the for loops you can store this instead:
size_t chars_to_copy;
for(arraycntr = 0, chars_to_copy = strlen(temp) + 1;
arraycntr < chars_to_copy;
arraycntr++)
{
s1[arraycntr] = temp[arraycntr];
}

Resources