我的一位朋友在雅虎的采访中被问到以下问题:
给定一个“abbccc”形式的字符串print“a1b2c3”。编写一个接受字符串并返回字符串的函数。照顾所有特殊情况。
你会如何编写专家代码?
非常感谢
答案 0 :(得分:15)
if (0==strcmp(s, "abbccc"))
return "a1b2c3";
else
tip_the_interviewer(50);
照顾。
答案 1 :(得分:11)
有多种方法可以做到这一点,但我可能会在输入字符串上运行两次:一次计算输出需要多少字节,然后分配输出缓冲区并再次实际生成输出。
另一种可能性是在输入字符串中加前两倍的字节数(加一),然后将输出写入其中。这使代码更简单,但可能非常浪费内存。由于操作看起来像一个基本压缩(RLE),也许最好是第一个实现没有输出占用输入内存的两倍。
另一种可能性是进行单次传递,并根据需要重新分配输出字符串,可能会以指数方式增加大小以确保O(N)整体性能。这在C中非常繁琐,所以可能不是函数的初始实现,特别是在面试条件下。它也不一定比我的第一个版本快。
然而,它已经完成,显而易见的“特殊情况”是一个空输入字符串,因为显而易见的(对我而言)实现将从存储第一个字符开始,然后进入循环。写输出可能不明确的东西也很容易:“1122”是输入“122”的输出,但也许它也是由122个1
个字符组成的输入的输出。因此,您可能希望将运行长度限制为最多9个字符(假设基数为10)以防止出现歧义。这取决于函数的用途 - 从单个示例输入和输出中调用完整的函数规范是不可能的。
设计界面还有不止一种方法:问题是“返回一个字符串”,所以大概是在用malloc
新分配的缓冲区中的NUL终止字符串。但是,从长远来看,这并不总是编写所有字符串API的好方法。在一个真实的项目中,我更愿意设计一个函数,它将要处理的字符串作为输入,连同指向输出缓冲区的指针和缓冲区的长度。它返回写入的字节数,或者如果输出缓冲区不够大,则返回已写入的数字。使用这个新功能实现所述功能很简单:
char *stated_function(const char *in) {
size_t sz = new_function(in, NULL, 0);
char *buf = malloc(sz);
if (buf) new_function(in, buf, sz);
return buf;
}
我也很困惑“打印”在问题中意味着什么 - 其他回答者将其视为“写入stdout”,意味着不需要分配。面试官是否想要一个打印编码字符串的函数,而会返回它?打印并返回其他内容?只返回一个字符串,当它们不是真的意思时使用“print”吗?
答案 2 :(得分:4)
遵循以下算法并实施它。
答案 3 :(得分:3)
这有点像家庭作业问题,但代码写起来太有趣了。
关键想法:
first
始终指向一系列相同字符中的第一个。beyond
指向一行相同字符的结尾。valgrind
报告没有内存错误。代码:
char *runcode(const char *s) {
char *t = malloc(2 * strlen(s) + 1); // eventual answer
assert(t);
char *w = t; // writes into t;
const char *first, *beyond; // mark limits of a run in s
for (first = s; *first; first = beyond) { // for each run do...
beyond = first+1;
while (*beyond == *first) beyond++; // move to end of run
*w++ = *first; // write char
w += sprintf(w, "%d", beyond-first); // and length of run
}
*w = '\0';
return t;
}
我喜欢的事情:
答案 4 :(得分:2)
正如其他人所指出的,该规范含糊不清。我认为对于面试问题来说这很好:关键在于看看求职者在模棱两可的情况下做了什么。
这是我对代码的看法。我做了一些假设(因为在这种情况下我不能很好地询问面试官):
我希望代码足够清晰,能够独立存在。我已经包含了一个测试工具和一些测试用例。
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
static void append(char **output, size_t *max, int c)
{
if (*max > 0) {
**output = c;
*output += 1;
*max -= 1;
}
}
static void encode(char **output, size_t *max, int c, int count)
{
while (count > 9) {
append(output, max, c);
append(output, max, '0' + 9);
count -= 9;
}
append(output, max, c);
append(output, max, '0' + count);
}
static bool rle(const char *input, char *output, size_t max)
{
char prev;
int count;
prev = '\0';
count = 0;
while (*input != '\0') {
if (*input == prev) {
count++;
} else {
if (count > 0)
encode(&output, &max, prev, count);
prev = *input;
count = 1;
}
++input;
}
if (count > 0)
encode(&output, &max, prev, count);
if (max == 0)
return false;
*output = '\0';
return true;
}
int main(void)
{
struct {
const char *input;
const char *facit;
} tests[] = {
{ "", "" },
{ "a", "a1" },
{ "aa", "a2" },
{ "ab", "a1b1" },
{ "abaabbaaabbb", "a1b1a2b2a3b3" },
{ "abbccc", "a1b2c3" },
{ "1", "11" },
{ "12", "1121" },
{ "1111111111", "1911" },
{ "aaaaaaaaaa", "a9a1" },
};
bool errors;
errors = false;
for (int i = 0; i < sizeof(tests) / sizeof(tests[0]); ++i) {
char buf[1024];
bool ok;
ok = rle(tests[i].input, buf, sizeof buf);
if (!ok || strcmp(tests[i].facit, buf) != 0) {
printf("FAIL: i=%d input=<%s> facit=<%s> buf=<%s>\n",
i, tests[i].input, tests[i].facit, buf);
errors = true;
}
}
if (errors)
return EXIT_FAILURE;
return 0;
}
答案 5 :(得分:1)
该死的,以为你说的是C#,而不是C.这是我感兴趣的C#实现。
private string Question(string input)
{
var output = new StringBuilder();
while (!string.IsNullOrEmpty(input))
{
var first = input[0];
var count = 1;
while (count < input.Length && input[count] == first)
{
count++;
}
if (count > input.Length)
{
input = null;
}
else
{
input = input.Substring(count);
}
output.AppendFormat("{0}{1}", first, count);
}
return output.ToString();
}
答案 6 :(得分:1)
int priya_homework(char *input_str, char *output_str, int out_len)
{
char pc,c;
int count=0,used=0;
/* Check for NULL and empty inputs here and return*/
*output_str='\0';
pc=*input_str;
do
{
c=*input_str++;
if (c==pc)
{
pc=c;
count++;
}
else
{
used=snprintf(output_str,out_len,"%c%d",pc,count);
if (used>=out_len)
{
/* Output string too short */
return -1;
}
output_str+=used;
out_len-=used;
pc=c;
count=1;
}
} while (c!='\0' && (out_len>0));
return 0;
}
答案 7 :(得分:0)
这样的事情:
void so(char s[])
{
int i,count;
char cur,prev;
i = count = prev = 0;
while(cur=s[i++])
{
if(!prev)
{
prev = cur;
count++;
}
else
{
if(cur != prev)
{
printf("%c%d",prev,count);
prev = cur;
count = 1;
}
else
count++;
}
}
if(count)
printf("%c%d",prev,count);
printf("\n");
}