It's quite common to work with non-null-terminated text data in C.  You just have to be careful with your terminology, because such data is not, formally, a "string".
If you have some text data that's not terminated by a null character, you obviously have to keep track of its length some other way.  The most common way is to keep a separate variable (often called n, size, sz, length, or len) containing the length.
For most operations which work on strings, there is a corresponding way to work with non-null-terminated text data.  Here is a table:
| operation | conventional string | counted text | 
| read from file | fgets | fread,read | 
| copy | strcpy | memcpy | 
| compute length | strlen | n/a | 
| write to file | fputs | fwrite,write | 
 
You can create an array containing a non-null-terminated "string" using a trick:
char nonstr[5] = "hello";
Normally, when you initialize a char array with a string literal, the C compiler picks the size, and includes space for the null terminator.  That is, when you write
char str[] = "hello";
the array comes out with a size of 6.  But when you specify an explicit size, and when it's "too small" by exactly 1, you get a non-null-terminated string.  To summarize:
char  error[3] = "hello";    /* error: array too small */
char nonstr[5] = "hello";    /* special case: no null */
char string[6] = "hello";    /* normal case: right size, including null */
char extra[10] = "hello";    /* extra space (could contain larger string later) */
char default[] = "hello";    /* default case: compiler picks size 6 */