嗨:)我正在尝试做的是编写一个简单的程序,以便从最短的条目扩展
例如
a-z或0-9或a-b-c或a-z0-9
写得最长
例如
abc ... xyz或0123456789或abc或abcdefghijklmnouprstwxyz0123456789
1-st examle shortst entry = 1-example示例结果,应该给出:))
到目前为止,我写了类似这样的内容,它仅适用于从a到z的字母:
expand(char s[])
{
int i,n,c;
n=c=0;
int len = strlen(s);
for(i = 1;s[i] > '0' && s[i]<= '9' || s[i] >= 'a' && s[i] <= 'z' || s[i]=='-';i++)
{
/*c = s[i-1];
g = s[i];
n = s[i+1];*/
if( s[0] == '-')
printf("%c",s[0]);
else if(s[i] == '-')
{
if(s[i-1]<s[i+1])
{
while(s[i-1] <= s[i+1])
{
printf("%c", s[i-1]);
s[i-1]++;
}
}
else if(s[i-1] == s[i+1])
printf("%c",s[i]);
else if(s[i+1] != '-')
printf("%c",s[i]);
else if(s[i-1] != '-')
printf("%c",s[i]);
}
else if(s[i] == s[i+1])
{
while(s[i] == s[i+1])
{
printf("%c",s[i]);
s[i]++;
}
}
else if( s[len] == '-')
printf("%c",s[len]);
}
}
但现在我被卡住了:(
任何想法我应该检查我的程序是否正常工作?
编辑1: @Andrew Kozak(1)abcd(2)01234
感谢您提前:)
答案 0 :(得分:3)
以下是满足 same test as my earlier C++ version.
的C版本(约38条有效行)可以在http://ideone.com/sXM7b#info_3915048
上看到完整的测试程序,包括您的测试用例,我的和一些酷刑测试我很确定我夸大了要求,但
a-c-b
不会发生(char*) 0
)printf("%c", c)
每个字符。我提出了一些意见,以解释为什么会发生什么,但总的来说,你会发现代码更加清晰,无论如何,
*it=='-'
或predicate(*it)
只返回 false ,如果它是空字符。 Shortcut evaluation阻止我们访问过去的输入字符一个警告:我没有对输出缓冲区溢出执行了正确的检查(容量在2048个字符处硬编码)。我将把它留给读者作为众所周知的练习
最后但并非最不重要的一点,我做了这个原因:
不用多说,实现,包括测试用例:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
int alpha_range(char c) { return (c>='a') && (c<='z'); }
int digit_range(char c) { return (c>='0') && (c<='9'); }
char* expand(const char* s)
{
char buf[2048];
const char* in = s;
char* out = buf;
// parser state
int (*predicate)(char) = 0; // either: NULL (free state), alpha_range (in alphabetic range), digit_range (in digit range)
char lower=0,upper=0; // tracks lower and upper bound of character ranges in the range parsing states
// init
*out = 0;
while (*in)
{
if (!predicate)
{
// free parsing state
if (alpha_range(*in) && (in[1] == '-') && alpha_range(in[2]))
{
lower = upper = *in++;
predicate = &alpha_range;
}
else if (digit_range(*in) && (in[1] == '-') && digit_range(in[2]))
{
lower = upper = *in++;
predicate = &digit_range;
}
else *out++ = *in;
} else
{
// in a range
if (*in < lower) lower = *in;
if (*in > upper) upper = *in;
if (in[1] == '-' && predicate(in[2]))
in++; // more coming
else
{
// end of range mode, dump expansion
char c;
for (c=lower; c<=upper; *out++ = c++);
predicate = 0;
}
}
in++;
}
*out = 0; // null-terminate buf
return strdup(buf);
}
void dotest(const char* const input)
{
char* ex = expand(input);
printf("input : '%s'\noutput: '%s'\n\n", input, ex);
if (ex)
free(ex);
}
int main (int argc, char *argv[])
{
dotest("a-z or 0-9 or a-b-c or a-z0-9"); // from the original post
dotest("This is some e-z test in 5-7 steps; this works: a-b-c. This works too: b-k-c-e. Likewise 8-4-6"); // from my C++ answer
dotest("-x-s a-9 9- a-k-9 9-a-c-7-3"); // assorted torture tests
return 0;
}
测试输出:
input : 'a-z or 0-9 or a-b-c or a-z0-9'
output: 'abcdefghijklmnopqrstuvwxyz or 0123456789 or abc or abcdefghijklmnopqrstuvwxyz0123456789'
input : 'This is some e-z test in 5-7 steps; this works: a-b-c. This works too: b-k-c-e. Likewise 8-4-6'
output: 'This is some efghijklmnopqrstuvwxyz test in 567 steps; this works: abc. This works too: bcdefghijk. Likewise 45678'
input : '-x-s a-9 9- a-k-9 9-a-c-7-3'
output: '-stuvwx a-9 9- abcdefghijk-9 9-abc-34567'
答案 1 :(得分:2)
好的,我测试了你的程序,似乎几乎适用于所有情况。它只用两个字母/数字正确地扩展了a-z和其他扩展。当有更多的字母和数字时,它会失败。修复很简单,只需创建一个新的字符来保留最后打印的字符,如果当前打印的字符与最后一个字符匹配则跳过它。 a-z0-9场景不起作用,因为你忘了s [i]&gt; ='0'而不是s [i]&gt; '0'。代码是:
#include <stdio.h>
#include <string.h>
void expand(char s[])
{
int i,g,n,c,l;
n=c=0;
int len = strlen(s);
for(i = 1;s[i] >= '0' && s[i]<= '9' || s[i] >= 'a' && s[i] <= 'z' || s[i]=='-';i++)
{
c = s[i-1];
g = s[i];
n = s[i+1];
//printf("\nc = %c g = %c n = %c\n", c,g,n);
if(s[0] == '-')
printf("%c",s[0]);
else if(g == '-')
{
if(c<n)
{
if (c != l){
while(c <= n)
{
printf("%c", c);
c++;
}
l = c - 1;
//printf("\nl is %c\n", l);
}
else
{
c++;
while(c <= n)
{
printf("%c", c);
c++;
}
l = c - 1;
//printf("\nl is %c\n", l);
}
}
else if(c == n)
printf("%c",g);
else if(n != '-')
printf("%c",g);
else if(c != '-')
printf("%c",g);
}
else if(g == n)
{
while(g == n)
{
printf("%c",s[i]);
g++;
}
}
else if( s[len] == '-')
printf("%c",s[len]);
}
printf("\n");
}
int main (int argc, char *argv[])
{
expand(argv[1]);
}
这不是K&amp; R的问题吗?我想我在那里看到了它。无论如何,我希望我帮助过。
答案 2 :(得分:1)
基于现有函数分别处理“a-z”和“0-9”序列的事实,我们应该探讨它们相遇时会发生什么。跟踪你的代码(尝试在每一步打印每个变量的值 - 是的它会混乱,所以使用换行符),我相信你会在迭代时发现逻辑短路,例如,从“当前令牌是'y '和下一个标记是'z'“到”当前标记是'z'而下一个标记是'0'“。探索if()条件,你会发现它并没有涵盖所有可能性,即你已经覆盖了自己,如果你在&lt; - &gt; z范围内,在0&gt; 9范围内,或者完全等于' - ',但是你没有考虑在下一个角色的下一个角色处于一个(az或0-9)的末尾。
答案 3 :(得分:1)
为了好玩,我决定向自己证明C ++真的适合这种事情。
首先,让我更严格地定义要求:我认为它需要处理这些情况:
<子> 子>
int main()
{
const std::string in("This is some e-z test in 5-7 steps; this works: a-b-c. This works too: b-k-c-e. Likewise 8-4-6");
std::cout << "input : " << in << std::endl;
std::cout << "output: " << expand(in) << std::endl;
}
input :
这是 5 -7 步骤中的一些 e-z 测试;这有效: a-b-c 。这也有效: b-k-c-e 。同样 8-4-6
output:
这是 567 步骤中的 efghijklmnopqrstuvwxyz 测试;这有效: abc 。这也有效: bcdefghijk 。同样 45678
以下是C ++ 0x代码 1 (23包括空格,注释) 的实现(实际上是一些变体) >
static std::string expand(const std::string& in)
{
static const regex re(R"([a-z](?:-[a-z])+|[0-9](?:-[0-9])+)");
std::string out;
auto tail = in.begin();
for (auto match : make_iterator_range(sregex_iterator(in.begin(), in.end(), re), sregex_iterator()))
{
out.append(tail, match[0].first);
// char range bounds: the cost of accepting unordered ranges...
char a=127, b=0;
for (auto x=match[0].first; x<match[0].second; x+=2)
{ a = std::min(*x,a); b = std::max(*x,b); }
for (char c=a; c<=b; out.push_back(c++));
tail = match.suffix().first;
}
out.append(tail, in.end());
return out;
}
当然我作弊有点因为我正在使用Boost的regex iterators。我将针对性能与C版本进行比较。我宁愿期望C ++版本在50%的范围内竞争。但是,让我们看看GNU编译器为我们存储了什么样的惊喜:)
这是一个演示样本输入的完整程序。 _它还包含一些基准时间和一些折衷的变化
#include <set> // only needed for the 'slow variant'
#include <boost/regex.hpp>
#include <boost/range.hpp>
using namespace boost;
using namespace boost::range;
static std::string expand(const std::string& in)
{
// static const regex re(R"([a-z]-[a-z]|[0-9]-[0-9])"); // "a-c-d" --> "abc-d", "a-c-e-g" --> "abc-efg"
static const regex re(R"([a-z](?:-[a-z])+|[0-9](?:-[0-9])+)");
std::string out;
out.reserve(in.size() + 12); // heuristic
auto tail = in.begin();
for (auto match : make_iterator_range(sregex_iterator(in.begin(), in.end(), re), sregex_iterator()))
{
out.append(tail, match[0].first);
// char range bounds: the cost of accepting unordered ranges...
#if !SIMPLE_BUT_SLOWER
// debug 15.149s / release 8.258s (at 1024k iterations)
char a=127, b=0;
for (auto x=match[0].first; x<match[0].second; x+=2)
{ a = std::min(*x,a); b = std::max(*x,b); }
for (char c=a; c<=b; out.push_back(c++));
#else // simpler but slower
// debug 24.962s / release 10.270s (at 1024k iterations)
std::set<char> bounds(match[0].first, match[0].second);
bounds.erase('-');
for (char c=*bounds.begin(); c<=*bounds.rbegin(); out.push_back(c++));
#endif
tail = match.suffix().first;
}
out.append(tail, in.end());
return out;
}
int main()
{
const std::string in("This is some e-z test in 5-7 steps; this works: a-b-c. This works too: b-k-c-e. Likewise 8-4-6");
std::cout << "input : " << in << std::endl;
std::cout << "output: " << expand(in) << std::endl;
}
<子>
1 与g++-4.6 -std=c++0x
一起编译
子>
答案 4 :(得分:0)
这是一个 Java 实现。它扩展了类似于 0-9、a-z 和 A-Z 的字符范围。也许有一天有人会需要它,而 Google 会将他们带到此页面。
package your.package;
public class CharacterRange {
/**
* Expands character ranges similar to 0-9, a-z and A-Z.
*
* @param string a string to be expanded
* @return a string
*/
public static String expand(String string) {
StringBuilder buffer = new StringBuilder();
int i = 1;
while (i <= string.length()) {
final char a = string.charAt(i - 1); // previous char
if ((i < string.length() - 1) && (string.charAt(i) == '-')) {
final char b = string.charAt(i + 1); // next char
char[] expanded = expand(a, b);
if (expanded.length != 0) {
i += 2; // skip
buffer.append(expanded);
} else {
buffer.append(a);
}
} else {
buffer.append(a);
}
i++;
}
return buffer.toString();
}
private static char[] expand(char a, char b) {
char[] expanded = expand(a, b, '0', '9'); // digits (0-9)
if (expanded.length == 0) {
expanded = expand(a, b, 'a', 'z'); // lower case letters (a-z)
}
if (expanded.length == 0) {
expanded = expand(a, b, 'A', 'Z'); // upper case letters (A-Z)
}
return expanded;
}
private static char[] expand(char a, char b, char min, char max) {
if ((a > b) || !(a >= min && a <= max && b >= min && b <= max)) {
return new char[0];
}
char[] buffer = new char[(b - a) + 1];
for (int i = 0; i < buffer.length; i++) {
buffer[i] = (char) (a + i);
}
return buffer;
}
public static void main(String[] args) {
String[] ranges = { //
"0-9", "a-z", "A-Z", "0-9a-f", "a-z2-7", "0-9a-v", //
"0-9a-hj-kmnp-tv-z", "0-9a-z", "1-9A-HJ-NP-Za-km-z", //
"A-Za-z0-9", "A-Za-z0-9+/", "A-Za-z0-9-_" };
for (int i = 0; i < ranges.length; i++) {
String input = ranges[i];
String output = CharacterRange.expand(ranges[i]);
System.out.println("input: " + input);
System.out.println("output: " + output);
System.out.println();
}
}
}
输出:
input: 0-9
output: 0123456789
input: a-z
output: abcdefghijklmnopqrstuvwxyz
input: A-Z
output: ABCDEFGHIJKLMNOPQRSTUVWXYZ
input: 0-9a-f
output: 0123456789abcdef
input: a-z2-7
output: abcdefghijklmnopqrstuvwxyz234567
input: 0-9a-v
output: 0123456789abcdefghijklmnopqrstuv
input: 0-9a-hj-kmnp-tv-z
output: 0123456789abcdefghjkmnpqrstvwxyz
input: 0-9a-z
output: 0123456789abcdefghijklmnopqrstuvwxyz
input: 1-9A-HJ-NP-Za-km-z
output: 123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz
input: A-Za-z0-9
output: ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789
input: A-Za-z0-9+/
output: ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/
input: A-Za-z0-9-_
output: ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_